加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 编程开发 > Java > 正文

java LinkedHashSet

发布时间:2020-12-14 05:47:03 所属栏目:Java 来源:网络整理
导读:我一直在为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 m
我一直在为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());
    }
}

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

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

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

在情况1中,虽然equals方法被覆盖,但它永远不会被调用.这是否意味着如果不覆盖hashCode方法,add()方法不会检查对象是否相等?
在情况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方法之间的一般契约: –

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

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

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

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读