注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本。本博客将从源码角度带领大家学习关于HashSet的知识。

一HashSet的定义:

public class HashSet<E>
extends AbstractSet<E>
implements Set<E>, Cloneable, java.io.Serializable

可以看到HashSet继承自AbstractSet同时实现了Set,Cloneable,Serializable三个接口,其中Cloneable,Serializable这两个接口基本上是java集合框架中所有的集合类都要实现的接口。

二HashSet中的重要属性:

<strong>  </strong>private transient HashMap<E,Object> map;
private static final Object PRESENT = new Object();

可以看到HashSet中的属性非常少,其中第一个属性是HashMap对象,是HashSet中用来存储数据的,据此可知HashSet的底层是基于HashMap的,关于HashMap的详细讲解请参看我的博客:【java集合框架源码剖析系列】java源码剖析之HashMap,而第二个属性表示的是HashSet中HashMap实例的value,因为HashSet虽然底层是基于HashMap实现的,但是HashSet只用来存储Key,其Value是无意义,Value的值全部用第二个属性代替。



三HashSet内部的实现原理:我们来看一下其构造器

 public HashSet() {
map = new HashMap<>();
} public HashSet(Collection<? extends E> c) {
map = new HashMap<>(Math.max((int) (c.size()/.75f) + 1, 16));
addAll(c);
} public HashSet(int initialCapacity, float loadFactor) {
map = new HashMap<>(initialCapacity, loadFactor);
} public HashSet(int initialCapacity) {
map = new HashMap<>(initialCapacity);
} HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

可以看到HashSet供5个构造器,其中前四个都是在其内部创建一个HashMap的实例,(从这里更清楚的看到HashSet的底层是基于HashMap的)而第5个则是创建一个LinkedHashMap的实例,而且第5个构造器前面无public修饰,表明该构造器对外不公开,事实上仅仅供LinkedHashSet使用的。第二个构造器表明当使用一个集合c作为参数来构造一个HashSet的时候会调用addAll(c),我们来看一下其源码:

 public boolean addAll(Collection<? extends E> c) {
boolean modified = false;
for (E e : c)
if (add(e))
modified = true;
return modified;
} public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

可以看到在addAll中调用了add(),而在add(E)方法中可以清楚看到使用HashMap的put方法时第二个参数传入的都是PRESENT,这就说明了HashSet中只保存Key而不保存Value。

四HashSet中的重要方法:

 public boolean add(E e) {
return map.put(e, PRESENT)==null; } public boolean remove(Object o) {
return map.remove(o)==PRESENT;
} public void clear() {
map.clear();
}

可以看到HashSet中与HashMap中同名的方法全部都是调用的HashMap中的方法来实现的。

五总结:经过前面HashMap的源码剖析可以看到HashSet非常简单

1HashSet底层是基于HashMap的,但是仅仅用来保存Key,而不保存Value,因为HashSet的add()方法在调用HashMap的put方法的时候第二个参数传入的都是PRESENT这个固定的Object对象。

2可以看到HashSet中的add与remove等方法均无synchronized关键字修饰,即HashSet不是线程安全的,如果要使用同步的HashSet需要使用Collections集合类的静态方法,即Set s=Collections.synchronizedSet(new HashSet());

3HashSet中的值允许为null,因为HashSet底层是基于HashMap的,而HashMap允许插入null。

4HashSet中的元素不允许重复,因为HashSet底层是基于HashMap的,而HashMap不允许存在重复元素,因为在put时如果key相同则会替换之前的V值。

【java集合框架源码剖析系列】java源码剖析之HashSet的更多相关文章

  1. [转载] Java集合框架之小结

    转载自http://jiangzhengjun.iteye.com/blog/553191 1.Java容器类库的简化图,下面是集合类库更加完备的图.包括抽象类和遗留构件(不包括Queue的实现): ...

  2. Java集合框架体系JCF

    Java 集合框架体系作为Java 中十分重要的一环, 在我们的日常开发中扮演者十分重要的角色, 那么什么是Java集合框架体系呢? 在Java语言中,Java语言的设计者对常用的数据结构和算法做了一 ...

  3. Java集合框架使用总结

    Java集合框架使用总结 前言:本文是对Java集合框架做了一个概括性的解说,目的是对Java集合框架体系有个总体认识,如果你想学习具体的接口和类的使用方法,请参看JavaAPI文档. 一.概述数据结 ...

  4. 【java集合框架源码剖析系列】java源码剖析之TreeSet

    本博客将从源码的角度带领大家学习TreeSet相关的知识. 一TreeSet类的定义: public class TreeSet<E> extends AbstractSet<E&g ...

  5. 【java集合框架源码剖析系列】java源码剖析之TreeMap

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本.本博客将从源码角度带领大家学习关于TreeMap的知识. 一TreeMap的定义: public class TreeMap&l ...

  6. 【java集合框架源码剖析系列】java源码剖析之ArrayList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 本博客将从源码角度带领大家学习关于ArrayList的知识. 一ArrayList类的定义: public class Arr ...

  7. 【java集合框架源码剖析系列】java源码剖析之LinkedList

    注:博主java集合框架源码剖析系列的源码全部基于JDK1.8.0版本. 在实际项目中LinkedList也是使用频率非常高的一种集合,本博客将从源码角度带领大家学习关于LinkedList的知识. ...

  8. 【java集合框架源码剖析系列】java源码剖析之HashMap

    前言:之所以打算写java集合框架源码剖析系列博客是因为自己反思了一下阿里内推一面的失败(估计没过,因为写此博客已距阿里巴巴一面一个星期),当时面试完之后感觉自己回答的挺好的,而且据面试官最后说的这几 ...

  9. 【java集合框架源码剖析系列】java源码剖析之java集合中的折半插入排序算法

    注:关于排序算法,博主写过[数据结构排序算法系列]数据结构八大排序算法,基本上把所有的排序算法都详细的讲解过,而之所以单独将java集合中的排序算法拿出来讲解,是因为在阿里巴巴内推面试的时候面试官问过 ...

随机推荐

  1. 【Codeforces Round #435 (Div. 2) A B C D】

    CF比赛题目地址:http://codeforces.com/contest/862 A. Mahmoud and Ehab and the MEX ·英文题,述大意:      输入n,x(n,x& ...

  2. Android通过聚合数据API实现天气预报

    使用聚合数据的API 聚合数据地址:https://www.juhe.cn/ 在数据服务->生活常用->全国天气预报,申请天气预报的API使用的KEY 保存请求示例的地址,把您申请的KEY ...

  3. delphi弹出信息框大全

    1. 警告信息框 MessageBox(Handle,'警告信息框','警告信息框',MB_ICONWARNING);2.疑问信息框 MessageBox(Handle,'疑问信息框','疑问信息框' ...

  4. cocos2d-x-3.x 学习总结(一)

    这周学习了<cocos2d-x 3.x 游戏开发之旅>的第三章,做如下总结: 1.关于创建标签对象 书中是 Label* label = Label::create(); 可是总是提示出错 ...

  5. 2018春招实习笔试面试总结(PHP)

    博主双非渣本计算机软件大三狗一枚,眼看着春招就要结束了,现将自己所经历的的整个春招做一个个人总结. 首先就是关于投递计划,博主自己整理了一份各大公司的春招信息,包括网申地址,开始时间,结束时间,以及自 ...

  6. 软件测试assert

    之前实习做过一段时间测试,现做个总结: 实习测试的是一款CM系统(case 系统),来记录IT部门处理的维修,服务,反馈,预定服务等case:b/s架构,人少小项目,实习时间短,去了已经快完工,主要测 ...

  7. 59. Spiral Matrix II(中等,同54题)

    Given an integer \(n\), generate a square matrix filled with elements from 1 to \(n^2\) in spiral or ...

  8. js密码64加密

    可以在客户端对密码进行简单的64位加密,服务端对应使用64位解密即可. /** * * Base64 encode / decode * * @author * @date * @email */ f ...

  9. 【C#复习总结】匿名类型由来

    1 属性 这得先从属性开始说,为什么外部代码访问对象内部的数据用属性而不是直接访问呢,这样岂不是更方便一些,但是事实证明直接访问是不安全的.那么,Anders Hejlsberg(安德斯·海尔斯伯格) ...

  10. Java对象的创建 —— new之后JVM都做了什么?

    Java对象创建过程 1. 类加载检查 虚拟机遇到一条new指令时,首先将去检查这个指令的参数是否能在常量池中定位到一个类的符号引用,并且检查这个符号引用代表的类是否已经被加载.解析和初始化过.如果没 ...