java LinkedHashSet

Mag*_*gie 6 java hash scjp linkedhashset

我一直在学习的OCJP(原SCJP)和我碰到下面的例子,它使用LinkedHashSet传来:

public class Test{

    int size;

    public Test(int s){
       this.size = s;
    }

    @Override
    public boolean equals(Object obj) {
         return (this.size == ((Test)obj).size);
    }

    public static void main(String[] args) {
      LinkedHashSet<Test> s = new LinkedHashSet<Test>();
      s.add(new Test(1));
      s.add(new Test(2));
      s.add(new Test(1));
      System.out.println(s.size());
    }
}
Run Code Online (Sandbox Code Playgroud)

现在,是什么是显示的问题,如果:
1)实现保持如
2)的hashCode覆盖插入类测试,如下所示:

public int hashCode() {return size/5};
Run Code Online (Sandbox Code Playgroud)

运行和编译代码表明第一种情况下set的大小是3,而在第二种情况下它是2.为什么?

在情况1中,虽然equals方法被覆盖,但它永远不会被调用.这是否意味着如果不覆盖hashCode方法,add()方法不会检查对象是否相等?
在情况2中,具有给定实现的hashCode和给定的Test对象集始终返回相同的数字.这与默认的hashCode实现有什么不同,为什么它会导致equals被调用?

Roh*_*ain 10

如果不重写hashCode(),那么每个实例都会有哈希码从一些预先定义计算散列算法Object类.因此,您的所有实例都可能具有不同的哈希码值(尽管这不是确定的).手段,每个实例都会进入自己的.

现在,即使重写equals()方法使两个实例基于某个属性相等,它们的哈希码仍然不同.

因此,具有不同哈希码的两个实例永远不会相等.所以集合大小是3.因为它没有任何重复.


但是,当您hashCode()使用以下实现覆盖时: -

public int hashCode() {return size/5};
Run Code Online (Sandbox Code Playgroud)

它将返回相同的值size.所以具有相同值的实例size将具有相同的哈希码,并且因为你已经在equals方法的基础上对size它们进行了比较,所以它们将是equal因此它们将被认为是重复的Set,因此将被删除Set.size().因此,是2.

道德: - hashCode()无论何时覆盖equals()方法,都应该覆盖,以维护两种方法之间的一般契约.

hashcodeequals方法之间的一般合​​同: -

  • 当两个对象相等时,它们的哈希码必须相等
  • 当两个对象不相等时,它们的哈希码可以相等
  • hashCode算法应始终为同一对象生成相同的值.
  • 如果两个对象的hashCode不同,它们将不相等
  • 始终用于same attributes计算hashCode您用于比较两个实例的情况

强烈建议至少阅读一次: -