我写了一个程序如下:
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中的equals
和hashcode
有一个大致的概念,对Object
类型有一个大致的概念,等等。
有人能从概念上解释一下这个东西是如何在内部比较一个整数列表并发现它是否已经存在的吗?注意,只有当列表中元素的顺序相同时,它才有效。
2条答案
按热度按时间dtcbnfnu1#
HashSet
依赖于元素类型的equals
和hashCode
方法(在本例中为List
)。List
类型上这些方法的文档如下:equals
-将指定的对象与此列表进行相等性比较。当且仅当指定的对象也是一个列表,两个列表具有相同的大小,并且两个列表中所有对应的元素对都相等时,返回true。(如果Objects.equals(e1,e2),则两个元素e1和e2相等。)换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。hashCode
-返回此列表的哈希代码值。列表的哈希码被定义为以下计算的结果:这确保了list1.equals(list 2)意味着对于任何两个列表list 1和list 2,list1.hashCode()==list2.hashCode(),正如Object.hashCode()的一般约定所要求的那样。
也就是说,
List
的hashCode
和equals
实现只是对列表中的每个元素进行操作。v6ylcynt2#
HashSet#contains(Object o)
javadoc声明如下(强调我的):如果此集合包含指定的元素,则返回true。更正式地说,当且仅当这个集合包含一个元素e,使得(o==null?e==null:o.equals(e))。
因此,这意味着当您检查
s.contains(l2)
时,s
中的List
实际上是通过List#equals()
内部检查l2
是否相等。List#equals(Object o)
javadoc声明(强调我的):比较指定对象与此列表是否相等。当且仅当指定的对象也是一个列表,两个列表具有相同的大小,并且两个列表中所有对应的元素对都相等时,返回true。(两个元素e1和e2相等,如果(e1==null?e2==null:e1.equals(e2)).)**换句话说,如果两个列表包含相同顺序的相同元素,则它们被定义为相等。**此定义确保equals方法在List接口的不同实现中正常工作。
这就是为什么
l2
被发现包含在s
中,而l3
没有。