Java hashCode有疑问

时间:2011-04-12 05:00:28

标签: 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类会覆盖hashCode中的java.lang.Object方法。因此,值为“foo”的String个对象将被视为重复。测试类不会覆盖hashCode方法并最终使用java.lang.Object版本,并且此版本始终为每个对象返回不同的哈希码,因此添加的两个测试对象将被视为不同。

4 个答案:

答案 0 :(得分:5)

在这种情况下,它不是hashCode(),而是约equals()方法。 HashSet仍然是Set,其语义不允许重复。使用equals()方法检查重复项,如果是String,将返回true

但是,对于testequals()方法没有定义,它将使用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()和toString()是公共的。
  • 覆盖toString(),以便System.out.println()或其他方法可以看到有用的东西,比如对象的状态。
  • 使用==确定两个引用变量是否引用同一个对象。
  • 使用equals()确定两个对象是否有意义相同。
  • 如果不覆盖equals(),则对象将无法使用散列键。
  • 如果不覆盖equals(),则不能认为不同的对象是相等的。
  • 字符串和包装器覆盖equals()并制作好的哈希键。
  • 当覆盖equals()时,请使用instanceof运算符以确保您正在评估适当的类。
  • 覆盖equals()时,比较对象的重要属性。
  • 等于的equals()合同:
    一个反身:x.equals(x)为真。
    b。对称:如果x.equals(y)为真,则y.equals(x)必须为真。
    c。传递:如果x.equals(y)为真,并且y.equals(z)为真,则z.equals(x)为真。
    d。一致:多次调用x.equals(y)将返回相同的结果。
    e。 Null:如果x不为null,则x.equals(null)为false。
    f。如果x.equals(y)为true,则x.hashCode()== y.hashCode()为true。
  • 如果覆盖equals(),请覆盖hashCode()。
  • HashMap,HashSet,Hashtable,LinkedHashMap,&amp; LinkedHashSet使用散列。
  • 适当的hashCode()覆盖符合hashCode()契约。
  • 高效的hashCode()覆盖在其存储桶中均匀分配密钥。
  • 重写的equals()必须至少与其hashCode()配合一样精确。
  • 重申:如果两个对象相等,则它们的哈希码必须相等。
  • hashCode()方法为所有实例返回相同的值是合法的(虽然在实践中效率非常低)。

此外,如果实现equals和hashcode,则必须正确处理瞬态字段(如果有)。

Commons对EqualsBuilder和HashcodeBuilder有很好的实现。它们在Coomons Lang有售 http://commons.apache.org/lang/

我使用它们whenevr我需要实现equals和hashcode。