HashSet底层HashMap源码分析
在看HashSet源码的时候,意外发现底层HashMap保存的value居然不是null,而是保存一个Object作为Value。顿觉有悖常理,于是来分析一下:
HashSet的add方法:
public boolean add(E e) {return map.put(e, PRESENT)==null;}
可以看到这里调用底层HashMap的时候,往value里放了一个PRESENT,中文直译为“存在”,为什么叫PRESENT,很形象,待会解释。
我们再来看看PRESENT是什么:
private static final Object PRESENT = new Object();
PRESENT是一个类静态变量,也就是说整个类所有的value也就这么一个对象,而且这个对象根本没有任何意义。
带着问题去分析:
- 问题一:按理说,HashSet只需要判断是否重复(存在),压根就不需要存放value的呀,那么存放一个null不就好了?何必存一个没有意义的Object?这个问题需要解释问题二
- 问题二:为什么add方法需要返回值?返回值的意义是什么?
- 问题三:如果给value存null会发生什么?
先分析问题三,如果存了一个null,我们知道HashMap是允许null值的,那么我们去看看map.put方法,存null会怎么样:
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
/**
* Implements Map.put and related methods.
* @return previous value, or null if none
*/
看注释最后一行:返回这个key之前的value,如果这个key之前没有value,那么返回null。
如果我们HashSet存null进去,那么分析一下返回值:
- 如果HashSet中已有了这个key,比如Set中已经有了一个KV:("张三", null),又填进去一个KV:("张三", null),此时应当返回privous value,也就是null
- 如果HashSet中没有这个key,比如第一次添加KV:("张三", null),那么应当返回null
发现问题了,如果HashSet中把null存为value,那么无论set中是否已有重复,add方法都会返回null,那么add方法就无法检验是否重复。
问题二也顺带解决了,add方法返回值,就是判断HashMap.put方法返回是否为null,也就是判断add方法添加的新元素是否已经重复。
问题一也解决了,这个Object本身确实没有意义,但是它对我们Set有意义:
它唯一的意义就是,它不等于null呀。。。也就是说,只要你开心,你往里放个什么东西都行。(毕竟还是要考虑内存占用的)
现在你肯定知道为什么这个Object叫“存在”了吧?因为张麻子说过,你和钱对我都不重要,有你,对我很重要。
HashSet底层HashMap源码分析的更多相关文章
- jdk7 HashSet和HashMap源码分析
先来看看HashMap的一些成员变量以及他们的含义 /** * The default initial capacity - MUST be a power of two. */ static fin ...
- Java HashMap源码分析(含散列表、红黑树、扰动函数等重点问题分析)
写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...
- Java中HashMap源码分析
一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...
- HashMap源码分析和应用实例的介绍
1.HashMap介绍 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射.HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.S ...
- Java HashSet和HashMap源码剖析
转自: Java HashSet和HashMap源码剖析 总体介绍 之所以把HashSet和HashMap放在一起讲解,是因为二者在Java里有着相同的实现,前者仅仅是对后者做了一层包装,也就是说Ha ...
- Java源码解析——集合框架(五)——HashMap源码分析
HashMap源码分析 HashMap的底层实现是面试中问到最多的,其原理也更加复杂,涉及的知识也越多,在项目中的使用也最多.因此清晰分析出其底层源码对于深刻理解其实现有重要的意义,jdk1.8之后其 ...
- 源码分析系列1:HashMap源码分析(基于JDK1.8)
1.HashMap的底层实现图示 如上图所示: HashMap底层是由 数组+(链表)+(红黑树) 组成,每个存储在HashMap中的键值对都存放在一个Node节点之中,其中包含了Key-Value ...
- 【JAVA集合】HashMap源码分析(转载)
原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...
- JDK1.8 HashMap源码分析
一.HashMap概述 在JDK1.8之前,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里.但是当位于一个桶中的元素较多,即hash值相等的元素较多时 ...
随机推荐
- 简单几步解决ie打不开闪退的问题 亲测有效
起因: 银行U盾插入 IE自动打开银行门户网站 打不开 闪退 不插入之后 IE还是闪退, 修复之法 清除IE扩展 一些自己安装的扩展或是被恶意安装的扩展插件会导致IE无法启动 1. 按住windows ...
- [AcWing 788] 逆序对的数量
点击查看代码 #include<iostream> using namespace std; typedef long long ll; const int N = 1e5 + 10; i ...
- [AcWing 771] 字符串中最长的连续出现的字符
点击查看代码 #include<iostream> using namespace std; string str; int n; int main() { cin >> n; ...
- wsgiref模块,动静态网页,jinja2模块,django
基于wsgiref模块搭建服务端 from wsgiref import simple_server def run(request, response): """ :p ...
- Mybatis-Plus乐观锁Version
实现原理 取出记录时,获取当前version更新时,带上这个version执行更新时, set version = newVersion where version = oldVersion如果ver ...
- linux篇-基于域名的apache服务器
1承接上个博客说的,咱们继续扩展 Cd /usr/local/apache2/conf /usr/local/apache2/conf/extra扩展文件 Vi httpd-vhosts.conf & ...
- 微信小程序避坑指南——echarts层级太高/层级遮挡
问题:小程序中echarts因为小程序原生的canvas层级太高,而导致弹窗这类dom元素无法遮挡住canvas,如下图: 解决方案1:(wx:if控制dom显隐,显示canvas就重新渲染echar ...
- 广义SAM
参考 还有首先你要会SAM吧~ 用途 相比与单串SAM,广义自动机能存储的是多个字符串. 有两种写法,第一种是离线利用trie树结构,第二种是在线伪广义SAM 离线+Trie 首先构建出trie树. ...
- CPPRESTSDK 编译
首先要 git clone这个库git clone git://github.com/Microsoft/cpprestsdk.git然后git 一下 Vcpkg.\vcpkg\bootstrap-v ...
- 技术分享 | app自动化测试(Android)--App 控件交互
原文链接 常用操作 点击操作 通常获取到元素之后,可以调用 click() 方法来实现对这个元素的点击操作.示例代码如下: python 版本 driver.find_element_by_id(&q ...