实际上,在带有流的Java 8中,这非常简单。编辑:没有流可以高效,请参阅下。
List<String> listA = Arrays.asList("2009-05-18","2009-05-19","2009-05-21");
List<String> listB = Arrays.asList("2009-05-18","2009-05-18","2009-05-19","2009-05-19",
"2009-05-20","2009-05-21","2009-05-21","2009-05-22");
List<String> result = listB.stream()
.filter(not(new HashSet<>(listA)::contains))
.collect(Collectors.toList());
请注意,哈希集仅创建一次:方法引用绑定到其contains方法。对lambda进行相同操作将需要将集合包含在变量中。制作变量并不是一个坏主意,尤其是当您发现它难看或难以理解时。
没有这种实用程序方法(或显式强制转换)之类的东西,您不能轻易地否定谓词,因为您不能直接调用否定方法引用(首先需要类型推断)。
private static <T> Predicate<T> not(Predicate<T> predicate) {
return predicate.negate();
}
如果流具有filterOut
方法或某种方法,它将看起来更好。
另外,@ Holger也给了我一个主意。ArrayList
其removeAll
方法针对多次移除进行了优化,它仅重新排列元素一次。但是,它使用contains
给定集合提供的方法,因此如果listA
很小,我们需要优化该部分。
使用listA
和listB
之前已声明,此解决方案不需要Java 8,并且非常有效。
List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));