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

Java中HashSet的实现原理是什么

Java中HashSet的实现原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习

Java中HashSet的实现原理是什么,很多新手对此不是很清楚,为了帮助大家解决这个难题,下面小编将为大家详细讲解,有这方面需求的人可以来学习下,希望你能有所收获。

HashSet来实现,因为它专门对快速查找进行了优化。

HashSet使用的是散列函数,那么它当中的元素也就无序可寻。当中是允许元素为null的。

先对实现原理进行一个总结:(1)基于HashMap实现的,默认构造函数是构建一个初始容量为16,负载因子为0.75 的HashMap。封装了一个 HashMap 对象来存储所有的集合元素,所有放入 HashSet 中的集合元素实际上由 HashMap 的 key 来保存,而 HashMap 的 value 则存储了一个 PRESENT,它是一个静态的 Object 对象。

(2)当我们试图把某个类的对象当成 HashMap的 key,或试图将这个类的对象放入 HashSet 中保存时,重写该类的equals(Object obj)方法和 hashCode() 方法很重要,而且这两个方法的返回值必须保持一致:当该类的两个的 hashCode() 返回值相同时,它们通过 equals() 方法比较也应该返回 true。通常来说,所有参与计算 hashCode() 返回值的关键属性,都应该用于作为 equals() 比较的标准。

(3)HashSet的其他操作都是基于HashMap的。

在这,为大家讲解HashSet 的实现原理:

它是基于HashMap实现的,HashSet底层使用HashMap来保存所有元素,因此HashSet 的实现比较简单,相关HashSet的操作,基本上都是直接调用底层HashMap的相关方法来完成, HashSet的源代码如下:

import java.util.AbstractSet;import java.util.Collection;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Set;import javax.swing.text.html.HTMLDocument.Iterator;public class HashSet      extends AbstractSet      implements Set, Cloneable, java.io.Serializable { static final long serialVersiOnUID= -5024744406713321676L; // 底层使用HashMap来保存HashSet中所有元素。 private transient HashMap map;  // 定义一个虚拟的Object对象作为HashMap的value,将此对象定义为static final。 private static final Object PRESENT = new Object();  // 默认的无参构造器,构造一个空的HashSet。 //  // 实际底层会初始化一个空的HashMap,并使用默认初始容量为16和加载因子0.75。  public HashSet() { map = new HashMap(); }  // 构造一个包含指定collection中的元素的新set。 // // 实际底层使用默认的加载因子0.75和足以包含指定 // collection中所有元素的初始容量来创建一个HashMap。 // @param c 其中的元素将存放在此set中的collection。  public HashSet(Collection c) { map = new HashMap(Math.max((int) (c.size()/.75f) + 1, 16)); addAll(c); }  // 以指定的initialCapacity和loadFactor构造一个空的HashSet。 // // 实际底层以相应的参数构造一个空的HashMap。 // @param initialCapacity 初始容量。 // @param loadFactor 加载因子。   public HashSet(int initialCapacity, float loadFactor) { map = new HashMap(initialCapacity, loadFactor); }  // 以指定的initialCapacity构造一个空的HashSet。 // // 实际底层以相应的参数及加载因子loadFactor为0.75构造一个空的HashMap。 // @param initialCapacity 初始容量。  public HashSet(int initialCapacity) { map = new HashMap(initialCapacity); } // 以指定的initialCapacity和loadFactor构造一个新的空链接哈希集合。 // 此构造函数为包访问权限,不对外公开,实际只是是对LinkedHashSet的支持。 // // 实际底层会以指定的参数构造一个空LinkedHashMap实例来实现。 // @param initialCapacity 初始容量。 // @param loadFactor 加载因子。 // @param dummy 标记。   HashSet(int initialCapacity, float loadFactor, boolean dummy) { map = new LinkedHashMap(initialCapacity, loadFactor); }  // 返回对此set中元素进行迭代的迭代器。返回元素的顺序并不是特定的。 // // 底层实际调用底层HashMap的keySet来返回所有的key。 // 可见HashSet中的元素,只是存放在了底层HashMap的key上, // value使用一个static final的Object对象标识。 // @return 对此set中元素进行迭代的Iterator。  public Iterator iterator() {    return map.keySet().iterator(); }  // 返回此set中的元素的数量(set的容量)。 // // 底层实际调用HashMap的size()方法返回Entry的数量,就得到该Set中元素的个数。 // @return 此set中的元素的数量(set的容量)。  public int size() { return map.size(); }  // 如果此set不包含任何元素,则返回true。 // // 底层实际调用HashMap的isEmpty()判断该HashSet是否为空。 // @return 如果此set不包含任何元素,则返回true。  public boolean isEmpty() { return map.isEmpty(); }  // 如果此set包含指定元素,则返回true。 // 更确切地讲,当且仅当此set包含一个满足(o==null ? e==null : o.equals(e)) // 的e元素时,返回true。 // // 底层实际调用HashMap的containsKey判断是否包含指定key。 // @param o 在此set中的存在已得到测试的元素。 // @return 如果此set包含指定元素,则返回true。  public boolean contains(Object o) { return map.containsKey(o); } // 如果此set中尚未包含指定元素,则添加指定元素。 // 更确切地讲,如果此 set 没有包含满足(e==null ? e2==null : e.equals(e2)) // 的元素e2,则向此set 添加指定的元素e。 // 如果此set已包含该元素,则该调用不更改set并返回false。 // // 底层实际将将该元素作为key放入HashMap。 // 由于HashMap的put()方法添加key-value对时,当新放入HashMap的Entry中key //与集合中原有Entry的key相同(hashCode()返回值相等,通过equals比较也返回true), //新添加的Entry的value会将覆盖原来Entry的value,但key不会有任何改变, // 因此如果向HashSet中添加一个已经存在的元素时,新添加的集合元素将不会被放入HashMap中, // 原来的元素也不会有任何改变,这也就满足了Set中元素不重复的特性。 // @param e 将添加到此set中的元素。 // @return 如果此set尚未包含指定元素,则返回true。  public boolean add(E e) {     return map.put(e, PRESENT)==null; } // 如果指定元素存在于此set中,则将其移除。 // 更确切地讲,如果此set包含一个满足(o==null ? e==null : o.equals(e))的元素e, // 则将其移除。如果此set已包含该元素,则返回true // (或者:如果此set因调用而发生更改,则返回true)。(一旦调用返回,则此set不再包含该元素)。 // // 底层实际调用HashMap的remove方法删除指定Entry。 // @param o 如果存在于此set中则需要将其移除的对象。 // @return 如果set包含指定元素,则返回true。  public boolean remove(Object o) { return map.remove(o)==PRESENT; }  // 从此set中移除所有元素。此调用返回后,该set将为空。 // // 底层实际调用HashMap的clear方法清空Entry中所有元素。  public void clear() { map.clear(); }  // 返回此HashSet实例的浅表副本:并没有复制这些元素本身。 // 底层实际调用HashMap的clone()方法,获取HashMap的浅表副本,并设置到HashSet中。  public Object clone() {   try {     HashSet newSet = (HashSet) super.clone();     newSet.map = (HashMap) map.clone();     return newSet;   } catch (CloneNotSupportedException e) {     throw new InternalError();   } } }

看完上述内容是否对您有帮助呢?如果还想对相关知识有进一步的了解或阅读更多相关文章,请关注编程笔记行业资讯频道,感谢您对编程笔记的支持。


推荐阅读
  • golang常用库:配置文件解析库/管理工具viper使用
    golang常用库:配置文件解析库管理工具-viper使用-一、viper简介viper配置管理解析库,是由大神SteveFrancia开发,他在google领导着golang的 ... [详细]
  • 本文详细介绍了Java中org.neo4j.helpers.collection.Iterators.single()方法的功能、使用场景及代码示例,帮助开发者更好地理解和应用该方法。 ... [详细]
  • Explore how Matterverse is redefining the metaverse experience, creating immersive and meaningful virtual environments that foster genuine connections and economic opportunities. ... [详细]
  • Explore a common issue encountered when implementing an OAuth 1.0a API, specifically the inability to encode null objects and how to resolve it. ... [详细]
  • 技术分享:从动态网站提取站点密钥的解决方案
    本文探讨了如何从动态网站中提取站点密钥,特别是针对验证码(reCAPTCHA)的处理方法。通过结合Selenium和requests库,提供了详细的代码示例和优化建议。 ... [详细]
  • Python 异步编程:深入理解 asyncio 库(上)
    本文介绍了 Python 3.4 版本引入的标准库 asyncio,该库为异步 IO 提供了强大的支持。我们将探讨为什么需要 asyncio,以及它如何简化并发编程的复杂性,并详细介绍其核心概念和使用方法。 ... [详细]
  • 优化ListView性能
    本文深入探讨了如何通过多种技术手段优化ListView的性能,包括视图复用、ViewHolder模式、分批加载数据、图片优化及内存管理等。这些方法能够显著提升应用的响应速度和用户体验。 ... [详细]
  • 本文将介绍如何编写一些有趣的VBScript脚本,这些脚本可以在朋友之间进行无害的恶作剧。通过简单的代码示例,帮助您了解VBScript的基本语法和功能。 ... [详细]
  • 本文详细介绍如何使用Python进行配置文件的读写操作,涵盖常见的配置文件格式(如INI、JSON、TOML和YAML),并提供具体的代码示例。 ... [详细]
  • Java 中的 BigDecimal pow()方法,示例 ... [详细]
  • 本文介绍了Java并发库中的阻塞队列(BlockingQueue)及其典型应用场景。通过具体实例,展示了如何利用LinkedBlockingQueue实现线程间高效、安全的数据传递,并结合线程池和原子类优化性能。 ... [详细]
  • 本文深入探讨了 Java 中的 Serializable 接口,解释了其实现机制、用途及注意事项,帮助开发者更好地理解和使用序列化功能。 ... [详细]
  • 本文详细介绍了Akka中的BackoffSupervisor机制,探讨其在处理持久化失败和Actor重启时的应用。通过具体示例,展示了如何配置和使用BackoffSupervisor以实现更细粒度的异常处理。 ... [详细]
  • Android 渐变圆环加载控件实现
    本文介绍了如何在 Android 中创建一个自定义的渐变圆环加载控件,该控件已在多个知名应用中使用。我们将详细探讨其工作原理和实现方法。 ... [详细]
  • 将Web服务部署到Tomcat
    本文介绍了如何在JDeveloper 12c中创建一个Java项目,并将其打包为Web服务,然后部署到Tomcat服务器。内容涵盖从项目创建、编写Web服务代码、配置相关XML文件到最终的本地部署和验证。 ... [详细]
author-avatar
yngbzl_165
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有