Set<List<Integer>> 在概念上是如何工作的

How Set<List<Integer>> is working conceptually

提问人:curiousengineer 提问时间:5/17/2023 最后编辑:Dinuxcuriousengineer 更新时间:5/17/2023 访问量:73

问:

我写了一个程序,如下所示:

public static void main(String[] args) {
        Set<List<Integer>> s = new HashSet<>();
        List<Integer> l1 = new ArrayList<>(List.of(1,2,3));
        List<Integer> l2 = new ArrayList<>(List.of(1,2,3));
        List<Integer> l3 = new ArrayList<>(List.of(3,2,1));
        s.add(l1);
        if(s.contains(l2)) {
            System.out.println("l2 is already present");
        }
        if(s.contains(l3)) {
            System.out.println("l3 is present");
        } else {
            System.out.println("l3 is absent");
        }
}

输出如下:

l2 is already present
l3 is absent

我对 Java 有一个大致的了解,对类型等有一个大致的概念。equalshashcodeObject

有人可以从概念上解释一下这个东西如何能够在内部比较整数列表并找到它是否已经存在?请注意,仅当列表中元素的顺序相同时,它才有效。

Java 对象类型

评论

6赞 Sweeper 5/17/2023
你到底想要什么样的解释? 因为。并且应该检查两个列表是否具有相同顺序的相等元素。s.contains(l2)l1.equals(l2)equals
3赞 maloomeister 5/17/2023
看着它的 javadoc 说:“......当且仅当此集合包含元素 e 使得 (o==null ? e==null : o.equals(e)).“时,返回 true。还有状态的 javadoc:“......如果两个列表以相同的顺序包含相同的元素,则它们被定义为相等。这种行为正是您在此处观察到的。HashSet#contains()List#equals()

答:

4赞 jon hanson 5/17/2023 #1

HashSet 依赖于元素类型的 和 方法(在本例中为 )。有关该类型的这些方法的文档如下:equalshashCodeListList

equals - 将指定对象与此列表进行比较,以确保相等。当且仅当指定的对象也是一个列表,两个列表具有相同的大小,并且两个列表中所有对应的元素对都相等时,才返回 true。(如果 Objects.equals(e1, e2),则两个元素 e1 和 e2 相等。换句话说,如果两个列表以相同的顺序包含相同的元素,则它们被定义为相等。
hashCode - 返回此列表的哈希代码值。列表的哈希代码被定义为以下计算的结果:

int hashCode = 1;
for (E e : list)
    hashCode = 31*hashCode + (e==null ? 0 : e.hashCode());

这确保了 list1.equals(list2) 意味着 list1.hashCode()==list2.hashCode() 对于任何两个列表 list1 和 list2,这是 Object.hashCode() 的一般合约所要求的。

即总而言之,s 的 和 实现只是对列表的每个元素进行操作。hashCodeequalsList

2赞 maloomeister 5/17/2023 #2

HashSet#contains(Object o) javadoc 声明如下(强调我的):

如果此集包含指定的元素,则返回 true。更正式地说,当且仅当此集合包含元素 e 时,返回 true 使得 (o==null ? e==null : o.equals(e))。

因此,这意味着当您检查 时,实际上会检查 s in 是否与内部 via 相等。s.contains(l2)Listsl2List#equals()

List#equals(Object o) javadoc 状态(强调我的):

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

这正是为什么被发现包含在 中,但事实并非如此。l2sl3