HashSet源码分析:

先来看一下它的构造方法:

呃~~居然它的底层是用HashMap来实现的,颠覆三观,那它究竟是如何来用的呢?继续来往下跟:

对于HashSet而言是没有key->value的结构的,那它是怎么跟HashMap关联到一块的呢?接着得查看add方法了:

也就是将我们往HashSet添加的元素是被用作HashMap的key,而HashMap的Value是一个常量,看一下它长啥样:

而这个字段也说明了,它是一个"Dummy value",也就是假的值,因为对于HashSet来说,只需要用到HashMap的key就行了,对于value不关心。

接着再来看一下删除元素的实现:

当然都是借助于HashMap来删除喽~


那它的其它方法其上差不多了,既然底层是由HashMap来实现的,那接下来就得探究一下HashMap的底层原理喽。

HashMap源码分析:

先来查看一下空的构造方法:

然后一句句代码来分析一下:

这有什么意义呢?这是因为通过散列来决定当前的元素达到总集合的75%时,则认为集合就快满了,所以就要考虑给集合进行扩容了,

这是干嘛滴,先不管,其中又用到了一个新的常量:

目前貌似一脸懵逼,不晓得这些变化是干嘛的,先放着,继续往下分析:


所以整个构造函数是初始化了一个长度为16的Entry类型的数组,那这个Entry又是啥呢?

接着再来分析放里面放元素的方法:

呃,貌似很复杂,但要想搞清楚原理必须得硬着头皮去读它,所以一句句来:

这个不太重要,往下继续:

注意:这个计算出来的并不是真正要添加的位置,真正要添加元素的位置在下一句,如下:

继续回到主流程:

那是如何添加的呢?继续查看该函数的实现,在查看之前先记住最后一个参数i,这是计算出来要存放的元素位置:

注意构造Entry的最后一个参数e:

也就是说将之前的元素做为新构建的Entry的下一个元素了,什么意思,下面用图来表示一下其添加的过程:

目前数组第一个元素已经有一个Entry1对象了,接着再put的时候散列位置时又散列到第一个元素了,此时添加时就会是:

这时就会将以前的那个元素作为新加入的Entry的next元素,因为Entry维护了一个next的引用。

总结:

  • HashSet底层是使用HashMap实现的。当使用add方法将对像添加到Set当中时,实际上是将该对象作为底层所维护的Map对象的key,而value则都是同一个Object对象(该对象我们用不上)。
  • HashMap底层维护一个数组,我们向HashMap中所放置的对象实际上是存储在该数组当中。
  • 当向HashMap中put一对键值时,它会根据key的hashcode值计算出一个位置,该位置就是此对象准备往数组中存放的位置。
  • 如果该位置没有对象存在,就将此对象直接放进数组当中;如果该位置已经有对象存在了,则顺着此存在的对象的链开始寻找(Entry类有一个Entry类型的next成员变量,指向了该对象的下一个对象),如果此链上有对象的话,再去使用equals方法进行比较,如果对此链上某个对象的equals方法比较为false,则将该对象放到数组当中,然后将数组中该位置放到数组当中,然后将数组中该位置以前存在的那个对象连接到此对象的后面。

HashSet与HashMap源代码深度剖析的更多相关文章

  1. Java HashSet和HashMap源码剖析

    转自: Java HashSet和HashMap源码剖析 总体介绍 之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说Ha ...

  2. HashMap源代码深入剖析

    ..

  3. HashMap源码深度剖析,手把手带你分析每一行代码,包会!!!

    HashMap源码深度剖析,手把手带你分析每一行代码! 在前面的两篇文章哈希表的原理和200行代码带你写自己的HashMap(如果你阅读这篇文章感觉有点困难,可以先阅读这两篇文章)当中我们仔细谈到了哈 ...

  4. 深度剖析HashMap的数据存储实现原理(看完必懂篇)

    深度剖析HashMap的数据存储实现原理(看完必懂篇) 具体的原理分析可以参考一下两篇文章,有透彻的分析! 参考资料: 1. https://www.jianshu.com/p/17177c12f84 ...

  5. 【Java集合源代码剖析】HashMap源代码剖析

    转载请注明出处:http://blog.csdn.net/ns_code/article/details/36034955 您好,我正在參加CSDN博文大赛,假设您喜欢我的文章.希望您能帮我投一票.谢 ...

  6. Java_深度剖析ConcurrentHashMap

    本文基于Java 7的源码做剖析. ConcurrentHashMap的目的 多线程环境下,使用Hashmap进行put操作会引起死循环,导致CPU利用率接近100%,所以在并发情况下不能使用Hash ...

  7. 深度剖析ConcurrentHashMap(转)

    概述 还记得大学快毕业的时候要准备找工作了,然后就看各种面试相关的书籍,还记得很多面试书中都说到: HashMap是非线程安全的,HashTable是线程安全的. 那个时候没怎么写Java代码,所以根 ...

  8. ASP.NET Core管道深度剖析(2):创建一个“迷你版”的管道来模拟真实管道请求处理流程

    从<ASP.NET Core管道深度剖析(1):采用管道处理HTTP请求>我们知道ASP.NET Core请求处理管道由一个服务器和一组有序的中间件组成,所以从总体设计来讲是非常简单的,但 ...

  9. Java反射机制剖析(四)-深度剖析动态代理原理及总结

    动态代理类原理(示例代码参见java反射机制剖析(三)) a)  理解上面的动态代理示例流程 a)  理解上面的动态代理示例流程 b)  代理接口实现类源代码剖析 咱们一起来剖析一下代理实现类($Pr ...

随机推荐

  1. 【VS开发】【C/C++开发】传递双重指针申请内存,典型用法

    传递双重指针申请内存,典型用法 指针参数是如何传递内存的? 如果函数的参数是一个指针,不要指望用该指针去申请动态内存.如下示例中,Test函数的语句GetMemory(str, 100)并没有使str ...

  2. Maven Web 工程

    本教程将教您如何在Eclipse中创建 Archetype为 maven-archetype-webapp的Maven项目,也就是web工程. 创建Maven工程 第一步,启动Eclipse,依次打开 ...

  3. Python全栈开发之7、面向对象编程进阶-类属性和方法、异常处理和反射

    一.类的属性 1.@property属性 作用就是通过@property把一个方法变成一个静态属性 class Room: def __init__(self,name,length,width,he ...

  4. PAT B1037 在霍格沃兹找零钱

    AC代码 #include <cstdio> #include <algorithm> using namespace std; char flag = 0; //判断付钱数是 ...

  5. Python基础『二』

    目录 语句,表达式 赋值语句 打印语句 分支语句 循环语句 函数 函数的作用 函数的三要素 函数定义 DEF语句 RETURN语句 函数调用 作用域 闭包 递归函数 匿名函数 迭代 语句,表达式 赋值 ...

  6. Sql 中的索引

    转载:https://www.cnblogs.com/hyd1213126/p/5828937.html

  7. Fabric的简介

    1,初识fabric 1,什么是fabric fabric是一个Python的库和命令行工具,用来提高基于SSH的应用部署和系统管理的效率. 简单来说: (1)一个让你通过命令行执行无参数python ...

  8. lua的数据类型

    Lua 是动态(弱)类型的语言,它有一下几种数据结构: nil(空) nil 类型表示一种没有任何有效值,它只有一个值 -- nil,例如打印一个没有赋值的变量,便会输出一个 nil 值: print ...

  9. Java super与this

    一.super()与this() 1.super(): 只能出现在子类构造器中 且必须位于第一行. 所有子类构造器默认调用super()方法 参数决定使用父类哪一个构造器. 若父类没有相应的构造器,则 ...

  10. ubuntu14.04 x86编译upx 3.92 及so加固

    的参考文章: http://www.cnblogs.com/fishou/p/4202061.html 1.download upx和所依赖的组件 upx3.:https://www.pysol.or ...