在看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源码分析的更多相关文章

  1. jdk7 HashSet和HashMap源码分析

    先来看看HashMap的一些成员变量以及他们的含义 /** * The default initial capacity - MUST be a power of two. */ static fin ...

  2. Java HashMap源码分析(含散列表、红黑树、扰动函数等重点问题分析)

    写在最前面 这个项目是从20年末就立好的 flag,经过几年的学习,回过头再去看很多知识点又有新的理解.所以趁着找实习的准备,结合以前的学习储备,创建一个主要针对应届生和初学者的 Java 开源知识项 ...

  3. Java中HashMap源码分析

    一.HashMap概述 HashMap基于哈希表的Map接口的实现.此实现提供所有可选的映射操作,并允许使用null值和null键.(除了不同步和允许使用null之外,HashMap类与Hashtab ...

  4. HashMap源码分析和应用实例的介绍

    1.HashMap介绍 HashMap 是一个散列表,它存储的内容是键值对(key-value)映射.HashMap 继承于AbstractMap,实现了Map.Cloneable.java.io.S ...

  5. Java HashSet和HashMap源码剖析

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

  6. Java源码解析——集合框架(五)——HashMap源码分析

    HashMap源码分析 HashMap的底层实现是面试中问到最多的,其原理也更加复杂,涉及的知识也越多,在项目中的使用也最多.因此清晰分析出其底层源码对于深刻理解其实现有重要的意义,jdk1.8之后其 ...

  7. 源码分析系列1:HashMap源码分析(基于JDK1.8)

    1.HashMap的底层实现图示 如上图所示: HashMap底层是由  数组+(链表)+(红黑树) 组成,每个存储在HashMap中的键值对都存放在一个Node节点之中,其中包含了Key-Value ...

  8. 【JAVA集合】HashMap源码分析(转载)

    原文出处:http://www.cnblogs.com/chenpi/p/5280304.html 以下内容基于jdk1.7.0_79源码: 什么是HashMap 基于哈希表的一个Map接口实现,存储 ...

  9. JDK1.8 HashMap源码分析

      一.HashMap概述 在JDK1.8之前,HashMap采用数组+链表实现,即使用链表处理冲突,同一hash值的节点都存储在一个链表里.但是当位于一个桶中的元素较多,即hash值相等的元素较多时 ...

随机推荐

  1. WorkCount

    此项目码云链接 软件测试方法和技术第二次作业 1 作业内容 根据WordCount的需求描述,先编程实现,再编写单元测试,最后撰写博客.至少完成需求中的基本功能. 2 WordCount需求说明 Wo ...

  2. 攻防世界-MISC:embarrass

    这是攻防世界高手进阶区的第二题,题目如下: 点击下载附件一,得到一个压缩包,解压后得到一个流量包 用wireshake打开,CTRL+F搜索字符串flag,记住要选择分组字节流 点击查找 在点击几次过 ...

  3. 基于SqlSugar的数据库访问处理的封装,在.net6框架的Web API上开发应用

    我前面几篇随笔介绍了关于几篇关于SqlSugar的基础封装,已经可以直接应用在Winform项目开发上,并且基础接口也通过了单元测试,同时测试通过了一些Winform功能页面:本篇随笔继续深化应用开发 ...

  4. 2003031121-浦娟-python数据分析五一假期作业

    项目 内容 课程班级博客链接 20级数据班(本) 这个作业要求链接 Python作业 博客名称 2003031121-浦娟-python数据分析五一假期作业 要求 每道题要有题目,代码(使用插入代码, ...

  5. 在GO中调用C源代码#基础篇1

    开坑说明 最近在编写客户端程序或与其他部门做功能集成时多次碰到了跨语言的sdk集成,虽说方案很多诸如rpc啊,管道啊,文件io啊,unix socket啊之类的不要太多,但最完美的基础方式还是让程序与 ...

  6. (Bezier)贝塞尔曲在路径规划的运用

    前言 之前被安排了活,一个局部区域机器运动控制的工作,大致是一个机器位于一个极限区域时候,机器要进入一个特殊的机制,使得机器可以安全的走出来.其中用到了bezier曲线进行优化路径,今天写一下,正好也 ...

  7. FTP主动模式上传文件时返回"ftp: accept: Resource temporarily unavailable"

    FTP主动模式上传文件时返回 Passive mode off ftp: accept: Resource temporarily unavailable 这个问题要从ftp的2种模式说起 PORT ...

  8. 【Java8新特性】Optional 类

    概述 Optional 类是一个可以为null的容器对象.如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象. Optional 是个容器:它可以保存类型T的值,或者 ...

  9. 590. N-ary Tree Postorder Traversal - LeetCode

    Question 590. N-ary Tree Postorder Traversal Solution 题目大意:后序遍历一个树 思路: 1)递归 2)迭代 Java实现(递归): public ...

  10. 数仓选型必列入考虑的OLAP列式数据库ClickHouse(上)

    概述 定义 ClickHouse官网地址 https://clickhouse.com/ 最新版本22.4.5.9 ClickHouse官网文档地址 https://clickhouse.com/do ...