在标准Java库中,找出两个list是否包含完全相同的元素的最简单方法是什么?

这两个list是否为相同实例并不重要,这两个list的类型参数是否不同也不重要。

e.g.

List list1
List<String> list2; 
// ... construct etc

list1.add("A");
list2.add("A"); 
// the function, given these two lists, should return true

我知道可能有什么东西在盯着我的脸:-)


编辑:为了澄清,我正在寻找完全相同的元素和元素的数量,按顺序。


当前回答

!集合。disjoint(Collection1, Collection2)如果它们有相同的元素,则返回true

其他回答

汤姆的回答很好,我完全同意他的回答!

这个问题的一个有趣方面是,您是否需要List类型本身及其固有顺序。

如果不是,你可以降级为Iterable或Collection,这让你在传递数据结构时具有一定的灵活性,这些数据结构是根据插入时间排序的,而不是在你想检查的时候排序。

如果顺序无关紧要(并且没有重复的元素),可以考虑使用Set。

如果顺序很重要,但由插入时间定义(并且没有重复),则考虑LinkedHashSet,它类似于TreeSet,但按插入时间排序(重复项不计算)。这也给了你O(1)个平摊访问,而不是O(log n)。

这应该在O(n)时间内完成。

public static <T> boolean isEqualCollection(Collection<T> c1, Collection<T> c2){
    if(nonNull(c1) && nonNull(c2)){
        Map<T, Long> c1Counts = c1.stream().collect(Collectors.groupingBy(i -> i, Collectors.counting()));
        for(T item : c2) {
            Long count  = c1Counts.getOrDefault(item, 0L);
            if(count.equals(0L)){
                return false;
            } else {
                c1Counts.put(item, count - 1L);
            }
        }
        return true;
    }
    return isNull(c1) && isNull(c2);
}

List上的equals方法可以做到这一点,列表是有序的,所以要相等,两个List必须具有相同的元素,且顺序相同。

return list1.equals(list2);
list1.equals(list2);

如果列表包含自定义类MyClass,则该类必须重写equals函数。

 class MyClass
  {
  int field=0;
  @0verride
  public boolean equals(Object other)
        {
        if(this==other) return true;
        if(other==null || !(other instanceof MyClass)) return false;
        return this.field== MyClass.class.cast(other).field;
        }
  }

注意:如果你想在java.util. set而不是java.util. set上测试equals。列表,则对象必须覆盖hashCode函数。

除了劳伦斯的答案,如果你也想让它为零安全:

private static <T> boolean listEqualsIgnoreOrder(List<T> list1, List<T> list2) {
    if (list1 == null)
        return list2==null;
    if (list2 == null)
        return list1 == null;
    return new HashSet<>(list1).equals(new HashSet<>(list2));
}