如何计算两个ArrayLists之间的差异?

nav*_*een 79 java arraylist

我有两个ArrayLists.

ArrayList A包含

['2009-05-18','2009-05-19','2009-05-21']
Run Code Online (Sandbox Code Playgroud)

ArrayList B包含 ['2009-05-18','2009-05-18','2009-05-19','2009-05-19','2009-05-20','2009-05-21','2009-05-21','2009-05-22']

我必须比较ArrayLst A和ArrayLst B. 结果ArrayList应该包含ArrayList中不存在的List .AllList结果应该是

[ '2009-05-20', '2009-05-22']

怎么比较?

Wil*_*del 188

在Java中,您可以使用Collection接口的removeAll方法.

// Create a couple ArrayList objects and populate them
// with some delicious fruits.
Collection firstList = new ArrayList() {{
    add("apple");
    add("orange");
}};

Collection secondList = new ArrayList() {{
    add("apple");
    add("orange");
    add("banana");
    add("strawberry");
}};

// Show the "before" lists
System.out.println("First List: " + firstList);
System.out.println("Second List: " + secondList);

// Remove all elements in firstList from secondList
secondList.removeAll(firstList);

// Show the "after" list
System.out.println("Result: " + secondList);
Run Code Online (Sandbox Code Playgroud)

上面的代码将产生以下输出:

First List: [apple, orange]
Second List: [apple, orange, banana, strawberry]
Result: [banana, strawberry]
Run Code Online (Sandbox Code Playgroud)

  • 如果您的列表是自定义类,那么您必须覆盖类的equals方法,对吧? (7认同)
  • @RTF是的,你需要提供[`equals`]的实现(http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#equals-java.lang.Object - )使您的对象能够进行比较.阅读有关实现[`hashCode`](http://docs.oracle.com/javase/8/docs/api/java/lang/Object.html#hashCode--)的内容.例如,请注意[`String :: equals`](http://docs.oracle.com/javase/8/docs/api/java/lang/String.html#equals-java.lang.Object-)是怎样的[区分大小写](https://en.wikipedia.org/wiki/Case_sensitivity),因此"apple"和"Apple"不会被视为相同. (5认同)
  • 这样效率很低.令人遗憾的是,这是被选中和评价最高的答案.`removeAll`在`secondList`的每个元素上调用`firstList.contains`.使用`HashSet`可以防止这种情况,并且有一些好的答案可以降低. (2认同)

and*_*rii 20

你已经有了正确的答案.如果你想在列表(集合)之间进行更复杂和有趣的操作,请使用apache commons集合(CollectionUtils)它允许你进行结合/分离,查找交集,检查一个集合是否是另一个集合的子集以及其他好东西.


Vla*_*sec 12

在带有流的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());
Run Code Online (Sandbox Code Playgroud)

请注意,哈希集仅创建一次:方法引用与其contains方法相关联.对lambda执行相同操作需要在变量中设置该集合.制作变量并不是一个坏主意,特别是如果你发现变得难看或难以理解.

如果没有像这个实用方法(或显式转换)之类的东西,你就不能轻易否定谓词,因为你不能直接调用negate方法引用(首先需要类型推断).

private static <T> Predicate<T> not(Predicate<T> predicate) {
    return predicate.negate();
}
Run Code Online (Sandbox Code Playgroud)

如果溪流有filterOut方法或东西,它会看起来更好.


Jos*_*osh 9

编辑:原始问题没有指定语言.我的答案是在C#中.

您应该使用HashSet来实现此目的.如果必须使用ArrayList,则可以使用以下扩展方法:

var a = arrayListA.Cast<DateTime>();
var b = arrayListB.Cast<DateTime>();    
var c = b.Except(a);

var arrayListC = new ArrayList(c.ToArray());
Run Code Online (Sandbox Code Playgroud)

使用HashSet ...

var a = new HashSet<DateTime>(); // ...and fill it
var b = new HashSet<DateTime>(); // ...and fill it
b.ExceptWith(a); // removes from b items that are in a
Run Code Online (Sandbox Code Playgroud)


Pet*_*erg 8

我使用过Guava Sets.difference.

参数是集合而不是常规集合,但是从任何集合(具有唯一项目)创建集合的便捷方式是Guava ImmutableSet.copyOf(Iterable).

(我首先在一个相关/重复问题上发布了这个问题,但我也在这里复制它,因为我觉得这是一个迄今为止缺失的好选择.)


jes*_*ana 8

虽然这是Java 8中一个非常古老的问题,但你可以做类似的事情

 List<String> a1 = Arrays.asList("2009-05-18", "2009-05-19", "2009-05-21");
 List<String> a2 = 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 = a2.stream().filter(elem -> !a1.contains(elem)).collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)

`