HashSet源码学习

一)、Set集合的主要使用类

1). HashSet

  基于对HashMap的封装

2). LinkedHashSet

  基于对LinkedHashSet的封装

3). TreeSet

  基于对TreeSet的封装

注: HashSet、 LinkedHashSet、 TreeSet的实现,都是委托其对应的map对象实现的。

二)、HashSet的特点

1).元素不能重复,元素的输入顺序和输出顺序不同。

2).内部维护一个HashMap对象,所有有关set的实现,都委托HashMap对象完成。

3).有关HashSet的一切性能特性和实现细节与HashMap完全相同。

三)、HashSet的主要属性

//内部对HashMap的封装
private transient HashMap<E,Object> map;
//内部封装的HashMap对应的value都指向Object PRESENT对象
private static final Object PRESENT = new Object();

四)、基于HashMap实现的add(E e)方法

创建一个HashSet对象:

//创建一个HashSet对象
HashSet<String> set = new HashSet<>();
System.out.println(set.add("a")); //true
System.out.println(set.add("a")); //false
//HashSet的元素不能重复
System.out.println(set.size()); // 1
//通过迭代器获取set中的元素
for(Iterator it = set.iterator() ; it.hasNext() ; ){
it.next();
} //创建HashMap对象,内部封装了一个HashMap对象
public HashSet() {
map = new HashMap<>();
}

添加元素:

set.add("a");

//添加元素
public boolean add(E e) {
//操作内部封装的HashMap对象,调用put方法
//key值不重复返回null,重复返回旧的value值
return map.put(e, PRESENT)==null;
}
//HashMap的put方法
public V put(K key, V value) {
return putVal(hash(key), key, value, false, true);
}
final V putVal(int hash, K key, V value, boolean onlyIfAbsent,
boolean evict) {
Node<K,V>[] tab; Node<K,V> p; int n, i;
if ((tab = table) == null || (n = tab.length) == 0)
n = (tab = resize()).length;
if ((p = tab[i = (n - 1) & hash]) == null)
tab[i] = newNode(hash, key, value, null);
else {
Node<K,V> e; K k;
//判断key值是否重复,若重复e = p ; 不等于null
if (p.hash == hash &&
((k = p.key) == key || (key != null && key.equals(k))))
e = p;
else if (p instanceof TreeNode)
e = ((TreeNode<K,V>)p).putTreeVal(this, tab, hash, key, value);
else {
for (int binCount = 0; ; ++binCount) {
if ((e = p.next) == null) {
p.next = newNode(hash, key, value, null);
if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st
treeifyBin(tab, hash);
break;
}
//判断key值是否重复
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
break;
p = e;
}
}
//key值重复的操作
if (e != null) { // existing mapping for key
//key值重复,将key对应的value修改为新值
V oldValue = e.value;
if (!onlyIfAbsent || oldValue == null)
e.value = value;
afterNodeAccess(e);
//返回旧value
return oldValue;
}
}
++modCount;
//key值不重复,size++, 返回null
if (++size > threshold)
resize();
afterNodeInsertion(evict);
return null;
}

HashSet源码学习,基于HashMap实现的更多相关文章

  1. 集合框架源码学习之HashMap(JDK1.8)

    目录: 0-1. 简介 0-2. 内部结构分析 0-2-1. JDK18之前 0-2-2. JDK18之后 0-3. LinkedList源码分析 0-3-1. 构造方法 0-3-2. put方法 0 ...

  2. JDK源码学习笔记——HashMap

    Java集合的学习先理清数据结构: 一.属性 //哈希桶,存放链表. 长度是2的N次方,或者初始化时为0. transient Node<K,V>[] table; //最大容量 2的30 ...

  3. HashSet源码学习

    一.介绍 1.HashSet 2.HashSet和HashMap的区别 1.相同点 HashSet 内部使用 HashMap 存储元素,对应的键值对的键为 Set 的存储元素,值为一个默认的 Obje ...

  4. 【jdk源码学习】HashMap

    package com.emsn.crazyjdk.java.util; /** * “人”类,重写了equals和hashcode方法...,以id来区分不同的人,你懂的... * * @autho ...

  5. Java集合专题总结(1):HashMap 和 HashTable 源码学习和面试总结

    2017年的秋招彻底结束了,感觉Java上面的最常见的集合相关的问题就是hash--系列和一些常用并发集合和队列,堆等结合算法一起考察,不完全统计,本人经历:先后百度.唯品会.58同城.新浪微博.趣分 ...

  6. JDK源码学习笔记——LinkedHashMap

    HashMap有一个问题,就是迭代HashMap的顺序并不是HashMap放置的顺序,也就是无序. LinkedHashMap保证了元素迭代的顺序.该迭代顺序可以是插入顺序或者是访问顺序.通过维护一个 ...

  7. 基于jdk1.8的HashMap源码学习笔记

    作为一种最为常用的容器,同时也是效率比较高的容器,HashMap当之无愧.所以自己这次jdk源码学习,就从HashMap开始吧,当然水平有限,有不正确的地方,欢迎指正,促进共同学习进步,就是喜欢程序员 ...

  8. 死磕Java之聊聊HashSet源码(基于JDK1.8)

    HashSet的UML图 HashSet的成员变量及其含义 public class HashSet<E> extends AbstractSet<E> implements ...

  9. Java集合类源码解析:HashMap (基于JDK1.8)

    目录 前言 HashMap的数据结构 深入源码 两个参数 成员变量 四个构造方法 插入数据的方法:put() 哈希函数:hash() 动态扩容:resize() 节点树化.红黑树的拆分 节点树化 红黑 ...

随机推荐

  1. jmeter-使用代理服务器录制脚本

    使用代理服务器录制脚本 1.测试计划-添加线程组 2.工作台添加HTTP代理服务器(路径:工作台-右键添加-非测试元件-HTTP代理服务器) 3.端口号一般由8888改为其他的 4.打开chrome的 ...

  2. Java代码优化建议

    总结日常Java开发常见优化策略,持续更新. 尽可能使用局部变量 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈中,速度较快,其他变量,如静态变量.实例变量等,都在堆中创建,速度较慢.另外, ...

  3. OsmocomBB软件实现栈概况

    OsmocomBB软件实现栈概况 简单地说,本文仅描述软件中GSM信号接收到部分. 暂不提及发送流程,引导加载/引导流程,以及各种控制路径特别是从layer1到RF硬件. 首先,通过天线接收RF信号, ...

  4. 解决tortoiseSvn 访问版本库的时候一直初始化,或者无响应的问题

    现象 svn访问版本库时一直提示: please wait while the repository browser is initializing 没有反应,甚至3-4分钟才会出来,即便出来也会很卡 ...

  5. (七)javac编译

    文章目录 1.基本格式 2.目标路径 2.1 缺省项 2.2 指定路径 2.2.1 全路径 2.2.2 相对路径 3.源文件 3.1 无第三方库 3.1.1 基本方法 3.1.2 添加目录 3.1.3 ...

  6. (三)django--带Template的网站

    我们接着(二),在new下新建一个templates(注意必须是这个名字,不然要进行配置),然后在该目录下新建一个test.html 2.我们在pycharm中新建的html文件里面不会有内容,我们输 ...

  7. MySQL 字段值为NULL,PHP用json转换,传给js,显示null

    这个问题出在php的json_encode环节,这个函数返回的json数据中会把空值写作null. 想通过在js端这样把null转为空字符串是不可以的: JSON.parse(JSON.stringi ...

  8. 第一篇:版本控制git之仓库管理

    ---恢复内容开始--- 再开始这个话题之前,让我想起了一件很痛苦的事情,在我大学写毕业论文的时候,我当时的文件是这样保存的 毕业论文_初稿.doc 毕业论文_修改1.doc 毕业论文_修改2.doc ...

  9. Android H5混合开发(4):构建Cordova Jar包

    前言 上一节,介绍了原生项目如何嵌入Cordova,我们对Cordova的依赖使用的是CordovaLib Module,这也是安卓项目常用的方式. 但是,也有项目希望以Jar包的方式依赖Cordov ...

  10. Luogu P2668 斗地主(NOIP2015)

    还记得那道我只用特判得了30分的"斗地主"吗? 我今天脑抽打算把它改A掉.为什么不用这大好时光去干些更有意义的事 于是我就挖了这个坑. 题解: 题目链接:P2668 斗地主 本题就 ...