java LinkedHashSet

前端之家收集整理的这篇文章主要介绍了java 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());
    }
}

现在,问题是如果显示内容:@H_404_5@1)实现保持原样@H_404_5@2)在类Test中插入hashCode的重写,如下所示:

public int hashCode() {return size/5};

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

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

解决方法

如果不覆盖hashCode(),那么每个实例都将具有根据Object类中的一些预定义哈希算法计算的哈希码.因此,您的所有实例都可能具有不同的哈希码值(尽管这不是确定的).手段,每个实例都会进入自己的桶.

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

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

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

public int hashCode() {return size/5};

它将返回相同大小的相同值.因此,具有相同大小值的实例将具有相同的哈希码,并且,因为您已根据大小在equals方法中对它们进行比较,因此它们将是相等的,因此它们将在您的Set中被视为重复,因此将被删除.所以,Set.size()是2.

道德: – 每当你重写equals()方法时,你应该总是覆盖hashCode(),以维护两个方法之间的一般契约.

hashcode和equals方法之间的一般契约: –

>当两个对象相等时,它们的哈希码必须相等@H_404_5@>当两个对象不相等时,它们的哈希码可以相等@H_404_5@> hashCode算法应始终为同一对象生成相同的值.@H_404_5@>如果两个对象的hashCode不同,它们将不相等@H_404_5@>始终使用相同的属性来计算用于比较两个实例的hashCode

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

> Effective Java - Item#9: Always override hashCode when you override equals

猜你在找的Java相关文章