我有这个程序:
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
类会覆盖hashCode
中的java.lang.Object
方法。因此,值为“foo”的String
个对象将被视为重复。测试类不会覆盖hashCode
方法并最终使用java.lang.Object
版本,并且此版本始终为每个对象返回不同的哈希码,因此添加的两个测试对象将被视为不同。
答案 0 :(得分:5)
在这种情况下,它不是hashCode()
,而是约equals()
方法。 HashSet仍然是Set,其语义不允许重复。使用equals()
方法检查重复项,如果是String,将返回true
但是,对于test
类equals()
方法没有定义,它将使用Object
中的默认实现,只有当两个引用都属于同一个实例时才会返回true。
方法hashCode()
用于不检查对象是否应该被视为相同,而是用于基于散列函数将它们分布在集合中。绝对有可能对于两个对象,此方法将返回相同的值,而equals()
将返回false。
P.S。 hashCode
Object
的实施并不保证价值的唯一性。使用简单循环检查很容易。
答案 1 :(得分:1)
Hashcode用于缩小搜索结果范围。当我们首先尝试在HashMap
中插入任何键时,它会检查是否存在任何其他对象具有相同的哈希码,如果是,则检查equals()
方法。如果两个对象相同,则HashMap
将不会添加该密钥,而是将新值替换为旧值。
答案 2 :(得分:0)
事实上,它不是覆盖hashcode()
,而是equals
方法。设置不允许重复。副本是对象在逻辑上相等的副本。
要验证您可以尝试使用
System.out.println(ws1.equals(ws2));
System.out.println(s1.equals(s2));
如果对象相等,则一组只能接受一个。
答案 3 :(得分:0)
下面是几个(很多很多)子弹从我准备SCJP中的平等和哈希码。 希望它有所帮助:
此外,如果实现equals和hashcode,则必须正确处理瞬态字段(如果有)。
Commons对EqualsBuilder和HashcodeBuilder有很好的实现。它们在Coomons Lang有售 http://commons.apache.org/lang/
我使用它们whenevr我需要实现equals和hashcode。