理解Java哈希集的方法

理解Java哈希集的方法,java,contains,hashset,Java,Contains,Hashset,关于java哈希集的新手问题 Set<User> s = new HashSet<User>(); User u = new User(); u.setName("name1"); s.add(u); u.setName("name3"); System.out.println(s.contains(u)); Set s=newhashset(); 用户u=新用户(); u、 设置名称(“名称1”); s、 加(u); u、 设置名称(“名称3”); System.ou

关于java哈希集的新手问题

Set<User> s = new HashSet<User>();
User u = new User();
u.setName("name1");
s.add(u);
u.setName("name3");
System.out.println(s.contains(u));
Set s=newhashset();
用户u=新用户();
u、 设置名称(“名称1”);
s、 加(u);
u、 设置名称(“名称3”);
System.out.println(s.contains(u));

有人能解释为什么这个代码输出为false吗?此外,该代码甚至不调用用户的equals方法。但是根据HashSet和HashMap的来源,它必须调用它。方法equals of User只调用用户名上的equals。方法hashCode返回用户名的hashCode

如果hash code方法基于
name
字段,然后在添加对象后对其进行更改,则第二个
contains
检查将使用新的hash值,并且不会找到您要查找的对象。这是因为
HashSet
s第一次按hash代码进行搜索,所以如果搜索失败,他们不会麻烦调用
equals

唯一可行的方法是,如果您没有重写
equals
(因此使用了默认的引用相等),并且您很幸运,两个对象的哈希代码是相等的。但这是一个非常不可能的情况,你不应该依赖它


一般来说,在将对象添加到
哈希集
后,如果该更改也会更改其哈希代码,则不应更新该对象。

由于新的
用户
具有不同的哈希代码,哈希集知道它不相等

哈希集根据其哈希代码存储其项。

HashSet仅在找到具有相同hashcode的项时调用
equals
,以确保这两个项实际上相等(与哈希冲突相反)

实际上,它仅在hashcode相等时调用equals。这意味着,如果我更新了User,它会更改hashCode,那么包含与其hashCode关联的条目的嵌套数组将不会被更新。所以在这个数组上迭代不会返回具有相同哈希代码的条目。如果hashCode始终返回0)正确,则应该可以工作。一般来说,将可变对象放入哈希集中是个坏主意。如果您使用
hashCode()
返回
0
,您将失去HashSet的所有性能优势,并最终得到可能得到的最慢的集合。我知道,这只是一个示例我相信这应该是公认的答案。值得注意的是,
HashSet.contains()
的javadoc没有说明只有在检查hashcode之后才应用等于。引用Jon Skeet的话,“HashSet中的对象应该是不可变的,或者在HashSet(或hashmap)中使用它们之后,您需要遵守不更改它们的规则。”-那么它是在哈希集中添加的u的副本?否则,我认为名称集中的对象也应该有名称3