在带有流的 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());
请注意,哈希集只创建一次:方法引用与其包含方法相关联。对 lambda 执行相同操作需要将集合放入变量中。制作变量并不是一个坏主意,尤其是当您发现它难看或难以理解时。
没有这种实用方法(或显式转换)之类的东西,你不能轻易地否定谓词,因为你不能直接调用否定方法引用(首先需要类型推断)。
private static <T> Predicate<T> not(Predicate<T> predicate) {
return predicate.negate();
}
如果流有filterOut
方法或其他东西,它会看起来更好。
另外,@Holger 给了我一个想法。ArrayList
它的removeAll
方法针对多次删除进行了优化,它只重新排列其元素一次。但是,它使用给定集合提供的方法,所以如果不是很小contains
的部分,我们需要优化该部分。listA
使用listA
andlistB
之前声明过,此解决方案不需要 Java 8,而且非常高效。
List<String> result = new ArrayList(listB);
result.removeAll(new HashSet<>(listA));