Java hashCode疑问
我有这个程序:
import java.util.*;
public class test {
private String s;
public test(String s) { this.s = s; }
public static void main(String[] args) {
HashSet<Object> hs = new HashSet<Object>();
test ws1 = new test("foo");
test ws2 = new test("foo");
String s1 = new String("foo");
String s2 = new String("foo");
hs.add(ws1);
hs.add(ws2);
hs.add(s1);
hs.add(s2); // removing this line also gives same output.
System.out.println(hs.size());
}
}
请注意,这不是作业。今天早些时候,我们在测验中被问到这个问题。我知道答案,但试图理解为什么会这样。
上面的程序给出 3 作为输出。
谁能解释一下这是为什么吗?
我认为(不确定):
java.lang.String
类覆盖了java.lang.Object
中的hashCode
方法。因此,值为“foo”的 String
对象将被视为重复项。测试类不会重写 hashCode 方法,最终使用 java.lang.Object 版本,并且该版本始终为每个对象返回不同的哈希码,因此这两个测试添加的对象被视为不同的。
I have this program:
import java.util.*;
public class test {
private String s;
public test(String s) { this.s = s; }
public static void main(String[] args) {
HashSet<Object> hs = new HashSet<Object>();
test ws1 = new test("foo");
test ws2 = new test("foo");
String s1 = new String("foo");
String s2 = new String("foo");
hs.add(ws1);
hs.add(ws2);
hs.add(s1);
hs.add(s2); // removing this line also gives same output.
System.out.println(hs.size());
}
}
Note that this is not a homework. We were asked this question on our quiz earlier today. I know the answers but trying to understand why it is so.
The above program gives 3 as output.
Can anyone please explain why that is?
I think (not sure):
The java.lang.String
class overrides the hashCode
method from java.lang.Object
. So the String
objects with value "foo" will be treated as duplicates. The test class does not override the hashCode
method and ends up using the java.lang.Object
version and this version always returns a different hashcode for every object, so the two test objects being added are treated as different.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(4)
在本例中,它与
hashCode()
无关,而是与equals()
方法有关。 HashSet仍然是Set,它具有不允许重复的语义。使用equals()
方法检查重复项,如果是字符串,将返回true
但是对于您的
test
类equals()< /code> 方法未定义,它将使用
Object
的默认实现,仅当两个引用都指向同一实例时才会返回 true。方法
hashCode()
不是用来检查对象是否应该被视为相同,而是作为一种基于哈希函数将它们分布在集合中的方法。对于两个对象,此方法完全有可能返回相同的值,而 equals() 则返回 false。PS
Object
的hashCode
实现不保证值的唯一性。使用简单的循环很容易检查。In this case it's not about
hashCode()
but is aboutequals()
method. HashSet is still Set, which has semantic of not allowing duplicates. Duplicates are checked for usingequals()
method which in case of String will returntrue
However for your
test
classequals()
method is not defined and it will use the default implementation fromObject
which will return true only when both references are to the same instance.Method
hashCode()
is used not to check if objects should be treated as same but as a way to distribute them in collections based on hash functions. It's absolutely possible that for two objects this method will return same value whileequals()
will return false.P.S.
hashCode
implementation ofObject
doesn't guarantee uniqueness of values. It's easy to check using simple loop.哈希码用于缩小搜索结果范围。当我们尝试在 HashMap 中插入任何键时,它首先检查是否存在具有相同哈希码的任何其他对象,如果是,则检查 equals() 方法。如果两个对象相同,则
HashMap
将不会添加该键,而是会用新值替换旧值。Hashcode is used to narrow down the search result. When we try to insert any key in
HashMap
first it checks whether any other object present with same hashcode and if yes then it checks for theequals()
method. If two objects are same thenHashMap
will not add that key instead it will replace the old value by new one.事实上,它不是关于重写
hashcode()
,而是关于equals
方法。 Set 不允许重复。重复对象是对象在逻辑上相等的对象。为了验证,您可以尝试使用“
如果对象相等,则一组只会接受一个”。
In fact, it is not about overriding the
hashcode()
, it is aboutequals
method. Set does not allow duplicates. A duplicate is the one where the objects are logically equal.For verifying you can try with
If the objects are equal, only one will be accepted by a set.
下面是一些(相当多)项目符号,重新定义了我为 SCJP 所做的准备工作中的 equals 和 hashcode。
希望它有帮助:
a.自反:x.equals(x) 为真。
b.对称:如果 x.equals(y) 为 true,则 y.equals(x) 也一定为 true。
c.传递性:如果 x.equals(y) 为 true,且 y.equals(z) 为 true,则 z.equals(x) 为 true。
D.一致:多次调用 x.equals(y) 将返回相同的结果。
e. Null:如果 x 不为 null,则 x.equals(null) 为 false。
f.如果 x.equals(y) 为 true,则 x.hashCode() == y.hashCode() 为 true。
此外,如果您实现 equals 和 hashcode,则必须正确处理瞬态字段(如果有)。
Commons 对 EqualsBuilder 和 HashcodeBuilder 有很好的实现。它们可在 Coomons Lang 中找到
http://commons.apache.org/lang/
当我需要实现 equals 时我使用它们和哈希码。
Below are few (well quite many) bullets refarding the equals and hashcode from my preparations to SCJP.
Hope it helps:
a. Reflexive: x.equals(x) is true.
b. Symmetric: If x.equals(y) is true, then y.equals(x) must be true.
c. Transitive: If x.equals(y) is true, and y.equals(z) is true, then z.equals(x) is true.
d. Consistent: Multiple calls to x.equals(y) will return the same result.
e. Null: If x is not null, then x.equals(null) is false.
f. If x.equals(y) is true, then x.hashCode() == y.hashCode() is true.
In addition if you implement equals and hashcode the transient fields (if any) must be treated properly.
The Commons have nice implementation for EqualsBuilder and HashcodeBuilder. They are available in Coomons Lang
http://commons.apache.org/lang/
I use them whenevr I need to implement the equals and the hashcode.