热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

为什么HashSet不能保持唯一性?

如何解决《为什么HashSet不能保持唯一性?》经验,为你挑选了2个好方法。

考虑员工类 -

public class Employer implements Serializable{

  private Long id;
  private String name;

  @Override
  public boolean equals(Object obj) {

    if (obj == null)
        return false;
    if (obj instanceof Employer) {
        Employer employer = (Employer) obj;
        if (this.id == employer.id) {
            return true;
        } 
    }
    return false;
  }

  //Idea from effective Java : Item 9
  @Override
  public int hashCode() {
    int result = 17;
    result = 31 * result + id.hashCode();
    //result = 31 * result + name.hashCode();
    return result;
  }
}

创建了2个员工对象 -

Employer employer1 = new Employer();
employer1.setId(10L);

Employer employer2 = new Employer();
employer2.setId(11L);

将它们添加到hashset后,大小将为2. HashSet内部使用hashmap来保持唯一性 -

private transient HashMap map;
public boolean add(E e) {
        return map.put(e, PRESENT)==null;
}

现在,如果我将第二个员工的id设置为与第一个员工的id相同,即 -

employer2.setId(10L);

大小仍然是2.为什么不是1?in-variants是否会被破坏?



1> Eran..:

大小仍然是2.为什么不是1?in-variants是否会被破坏?

如果修改用于计算的任何属性hashCode以及equals已在其中的实例HashSet,则HashSet实现不会知道该更改.

因此它将保留这两个实例,即使它们现在彼此相等.

您不应对作为成员或HashSets(或HashMaps中的键)的实例进行此类更新.如果您必须进行此类更改,请从变更Set之前删除该实例,然后再重新添加.



2> dasblinkenli..:

所有基于散列的容器(包括HashSet)都对其键的哈希代码做了一个非常重要的假设:它们假设哈希代码在对象位于容器内时永远不会改变.

您的代码通过在实例仍在哈希集中时修改实例来违反此假设.没有切实可行的方法HashSet来应对此更改,因此您必须选择以下两种方法之一来处理此问题:

永远不要修改基于散列的容器的密钥 - 这是迄今为止最常用的方法,通常通过使哈希密钥不可变来实现.

跟踪修改,并手动重新哈希对象 - 本质上,您的代码确保在哈希键位于容器外时对哈希键进行所有修改:从容器中删除对象,进行修改,然后将其放回原位.

第二种方法经常成为维护头痛的根源.当您需要在基于散列的容器中保留可变数据时,一种好的方法是final在计算哈希代码和相等性检查时仅使用字段.在您的示例中,这将意味着创建id字段final,并setId从类中删除方法.


推荐阅读
  • TheHashSetclasshasanadd(Objecto)method,whichisnotinheritedfromanotherclass.TheJavado ... [详细]
  • HashSet and HashMap
    HashSetandHashMap总体介绍之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说HashS ... [详细]
  • 这篇文章运用简单易懂的例子给大家介绍JAVAHashSet和TreeSet实现保证存入元素不会重复,内容非常详细,感兴趣的小伙伴们可以参考借鉴,希望对 ... [详细]
  • 本文讨论了微软的STL容器类是否线程安全。根据MSDN的回答,STL容器类包括vector、deque、list、queue、stack、priority_queue、valarray、map、hash_map、multimap、hash_multimap、set、hash_set、multiset、hash_multiset、basic_string和bitset。对于单个对象来说,多个线程同时读取是安全的。但如果一个线程正在写入一个对象,那么所有的读写操作都需要进行同步。 ... [详细]
  • 本文介绍了iOS数据库Sqlite的SQL语句分类和常见约束关键字。SQL语句分为DDL、DML和DQL三种类型,其中DDL语句用于定义、删除和修改数据表,关键字包括create、drop和alter。常见约束关键字包括if not exists、if exists、primary key、autoincrement、not null和default。此外,还介绍了常见的数据库数据类型,包括integer、text和real。 ... [详细]
  • 本文整理了Java面试中常见的问题及相关概念的解析,包括HashMap中为什么重写equals还要重写hashcode、map的分类和常见情况、final关键字的用法、Synchronized和lock的区别、volatile的介绍、Syncronized锁的作用、构造函数和构造函数重载的概念、方法覆盖和方法重载的区别、反射获取和设置对象私有字段的值的方法、通过反射创建对象的方式以及内部类的详解。 ... [详细]
  • Java容器中的compareto方法排序原理解析
    本文从源码解析Java容器中的compareto方法的排序原理,讲解了在使用数组存储数据时的限制以及存储效率的问题。同时提到了Redis的五大数据结构和list、set等知识点,回忆了作者大学时代的Java学习经历。文章以作者做的思维导图作为目录,展示了整个讲解过程。 ... [详细]
  • Spring特性实现接口多类的动态调用详解
    本文详细介绍了如何使用Spring特性实现接口多类的动态调用。通过对Spring IoC容器的基础类BeanFactory和ApplicationContext的介绍,以及getBeansOfType方法的应用,解决了在实际工作中遇到的接口及多个实现类的问题。同时,文章还提到了SPI使用的不便之处,并介绍了借助ApplicationContext实现需求的方法。阅读本文,你将了解到Spring特性的实现原理和实际应用方式。 ... [详细]
  • Java学习笔记之面向对象编程(OOP)
    本文介绍了Java学习笔记中的面向对象编程(OOP)内容,包括OOP的三大特性(封装、继承、多态)和五大原则(单一职责原则、开放封闭原则、里式替换原则、依赖倒置原则)。通过学习OOP,可以提高代码复用性、拓展性和安全性。 ... [详细]
  • Oracle seg,V$TEMPSEG_USAGE与Oracle排序的关系及使用方法
    本文介绍了Oracle seg,V$TEMPSEG_USAGE与Oracle排序之间的关系,V$TEMPSEG_USAGE是V_$SORT_USAGE的同义词,通过查询dba_objects和dba_synonyms视图可以了解到它们的详细信息。同时,还探讨了V$TEMPSEG_USAGE的使用方法。 ... [详细]
  • Whatsthedifferencebetweento_aandto_ary?to_a和to_ary有什么区别? ... [详细]
  • Netty源代码分析服务器端启动ServerBootstrap初始化
    本文主要分析了Netty源代码中服务器端启动的过程,包括ServerBootstrap的初始化和相关参数的设置。通过分析NioEventLoopGroup、NioServerSocketChannel、ChannelOption.SO_BACKLOG等关键组件和选项的作用,深入理解Netty服务器端的启动过程。同时,还介绍了LoggingHandler的作用和使用方法,帮助读者更好地理解Netty源代码。 ... [详细]
  • 如何解决《使用int数组的HashSet用法》经验,为你挑选了1个好方法。 ... [详细]
  • HiIhaveaHashSetlikethefollowinginaclasscalledMemory:嗨,我在一个名为Memory的类中有如下的HashSet:Set& ... [详细]
  • Imtryingtogetthetypeofanarrayelements.Igotsomethinglikethis:我正在尝试获取数组元素的类型。我有这样的事情: ... [详细]
author-avatar
大帅哥石头2011
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有