查找两个不同的列表是否包含完全相同的元素的简单方法?

2022-08-31 05:07:33

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

两个 List 是否为同一实例无关紧要,List 的类型参数是否不同也无关紧要。

例如:

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

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

可能有一些东西盯着我的脸,我知道:-)


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


答案 1

如果你关心顺序,那么只需使用等于方法:

list1.equals(list2)

来自 javadoc:

将指定的对象与此列表进行比较以确定是否相等。当且仅当指定的对象也是一个列表,两个列表具有相同的大小,并且两个列表中所有对应的元素对都相等,才返回 true。(两个元素 e1 和 e2 相等,如果 (e1==null ? e2==null : e1.equals(e2))。换言之,如果两个列表以相同的顺序包含相同的元素,则将其定义为相等。此定义可确保 equals 方法在 List 接口的不同实现中正常工作。

如果要独立于顺序进行检查,则可以将所有元素复制到 Sets,并在生成的 Sets 上使用 equals:

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

这种方法的局限性在于它不仅忽略了顺序,还忽略了重复元素的频率。例如,如果是[“A”,“B”,“A”]并且是[“A”,“B”,“B”],则方法将认为它们是相等的。list1list2Set

如果您需要对订单不敏感,但对重复的频率敏感,您可以:


答案 2

我在评论中发布了一堆东西,我认为它值得自己的答案。

正如大家在这里所说,使用 equals() 取决于顺序。如果你不关心订单,你有3个选择。

备选案文1

用。在我看来,这个选项并不理想,因为它提供了最坏情况的性能,O(n^2)。containsAll()

备选案文2

有两种变体:

2a)如果你不关心维护你的列表的顺序...在两个列表中使用。然后使用 .这是 O(nlogn),因为你做了两个排序,然后是 O(n) 比较。Collections.sort()equals()

2b) 如果您需要维护列表的顺序,可以先复制两个列表。然后,您可以在两个复制的列表上使用解决方案 2a。但是,如果复制非常昂贵,这可能没有吸引力。

这导致:

备选案文3

如果您的要求与第 2b 部分相同,但复制成本太高。您可以使用树集为您进行排序。将每个列表转储到其自己的树集中。它将在集合中排序,原始列表将保持不变。然后在两个 上执行比较。s 可以在 O(nlogn) 时间内构建,而 s 是 O(n)。equals()TreeSetTreeSetsequals()

选择:-)。

编辑:我几乎忘记了劳伦斯·贡萨尔维斯(Laurence Gonsalves)指出的同样的警告。TreeSet 实现将消除重复项。如果您关心重复项,则需要某种排序的多集。