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. 19.Linux进程管理概述

    1.进程基本概述 当我们运行一个程序,那么我们将运行的程序叫进程. PS1: 当程序运行为进程后,系统会为该进程分配内存,以及进程运行的身份和权限. PS2: 在进程运行的过程中,服务器上会有各种状态 ...

  2. c#菜单动态合并

    说明 在程序中经常使用弹出菜单,并且一个窗体中可以存在多个弹出菜单.开发过MDI窗体的读者可能都知道,当MDI子窗体最大化时,子窗体和主窗体的菜单能够自动的合并.这是如何实现的呢?本例实现了将两个弹出 ...

  3. 用Docker搭建一个支持https的nginx代理服务

    用Docker搭建一个支持https的nginx代理服务 说明:本文所提的服务只是作者平常测试使用,可能含有未知bug或不成熟的解决方案,仅供参考,请不要用于正式环境,当然,使用过程中有任何问题欢迎提 ...

  4. Activity 学习(二) 搭建第一个Activity流程框架

    本次示例使用的IDER测试完成 测试背景 : xx饿了去饭店吃饭  需要先和服务员点餐  点完餐后服务员将菜品传递给厨师制作  制作完成后吃饱 一 :创建流程图 创建上一篇测试成功出现的BpmnFil ...

  5. Java日志Log4j或者Logback的NDC和MDC功能

    NDC和MDC的区别 Java中使用的日志的实现框架有很多种,常用的log4j和logback以及java.util.logging,而log4j是apache实现的一个开源日志组件(Wrapped ...

  6. label 标签的 for 属相

    我的github iSAM2016 一开始学html 标签的时候,知道有label 这个标签的,但是并没有注意到他的for 属性的作用,看一下MDN的介绍 for 可标记的 form相关元素的ID,在 ...

  7. JavaWeb EL表达式 key为数值 Map取不到值

    JavaWeb  EL表达式 key为 Map取不到值 因为JSTL会把Integer,Byte,Short,Charactor都转成Long,这样就取不到值. 参见StackOverFlow的回答 ...

  8. oc基本知识

    (一)构造函数 h文件 #import <Foundation/Foundation.h> @interface Student : NSObject { NSString *_name; ...

  9. Linux文件同步工具之rsync

    学习背景 1.最近公司的项目在使用jenkins做自动化构建,因为jenkins在构建时是比较耗性能的,便单独使用了一台服务器做构建服务器.但是个人觉得这样成本过高,单独拿一台服务器来构建并且该服务器 ...

  10. Unity5-ABSystem(一):AssetBundle原理

    转载自:http://blog.csdn.net/lodypig/article/details/51863683 说明 AssetBundle简介 AssetBundle内部格式 normal bu ...