文档章节

【java集合框架源码剖析系列】java源码剖析之HashSet

htq
 htq
发布于 2016/07/26 09:41
字数 872
阅读 3
收藏 0

注:博主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值。

本文转载自:http://blog.csdn.net/htq__/article/details/51056462

共有 人打赏支持
htq

htq

粉丝 19
博文 67
码字总数 1007
作品 3
武汉
一份关于 Java、Kotlin 与 Android 的学习笔记

JavaKotlinAndroidLearn 这是一份关于 Java 、Kotlin 、Android 的学习笔记,既包含对基础知识点的介绍,也包含对一些重要知识点的源码解析,笔记的大纲如下所示: Java 重拾Java(0)-基础知...

叶应是叶
08/08
0
0
Java开发者不会这些永远都只能是三流程序员,细数一下你是不是?

源码系列 手写spring mvc框架 基于Spring JDBC手写ORM框架 实现自己的MyBatis Spring AOP实战之源码分析 Spring IOC高级特性应用分析 ORM框架底层实现原理剖析 手写Spring MVC框架实现 手把手...

美的让人心动
04/16
0
0
三流程序员与一流程序员之间的区别,看看你是属于哪一类?

源码系列 手写spring mvc框架 基于Spring JDBC手写ORM框架 实现自己的MyBatis Spring AOP实战之源码分析 Spring IOC高级特性应用分析 ORM框架底层实现原理剖析 手写Spring MVC框架实现 手把手...

茶轴的青春
04/17
0
0
sharding-jdbc源码分析—准备工作

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/7831817c1da8 接下来对sharding-jdbc源码的分析基于tag为源码,根据sharding-jdbc Features深入学习sharding-jdbc的几个主要特性...

飞哥-Javaer
05/03
0
0
【死磕Sharding-jdbc】—–路由&执行

原文作者:阿飞Javaer 原文链接:https://www.jianshu.com/p/09efada2d086 继续以模块中的为基础,剖析分库分表简单查询SQL实现--,即如何执行简单的查询SQL,接下来的分析以执行SQL语句为例...

飞哥-Javaer
05/03
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

最全最强解析:支付宝钱包系统架构内部剖析(架构图)

支付宝系统架构概况 典型处理默认 资金处理平台 财务会计 支付清算 核算中心 交易 柔性事务 支付宝的开源分布式消息中间件–Metamorphosis(MetaQ) Metamorphosis (MetaQ) 是一个高性能、高可...

晨猫
34分钟前
4
0
竞品分析

那什么样的场景需要用关键纬度分析法分析竞品呢? 竞品分析的目的是为了看竞品们和自己产品重合的业务都具备哪些功能点,以及这些功能是怎么做的,以此确定自己产品的优化方向。 竞品们的业务...

于谦老师
41分钟前
1
0
OSChina 周三乱弹 —— 公司女同事约我

Osc乱弹歌单(2018)请戳(这里) 【今日歌曲】 @莱布妮子:分享水木年华的单曲《蝴蝶花(2002年大提琴版)》 《蝴蝶花(2002年大提琴版)》- 水木年华 手机党少年们想听歌,请使劲儿戳(这里) ...

小小编辑
今天
1K
16
Linux环境搭建 | VMware下共享文件夹的实现

在进行程序开发的过程中,我们经常要在主机与虚拟机之间传递文件,比如说,源代码位于虚拟机,而在主机下阅读或修改源代码,这里就需要使用到 「共享文件」 这个机制了。本文介绍了两种共享文...

良许Linux
今天
9
0
JUC锁框架——AQS源码分析

JUC锁介绍 Java的并发框架JUC(java.util.concurrent)中锁是最重要的一个工具。因为锁,才能实现正确的并发访问。而AbstractQueuedSynchronizer(AQS)是一个用来构建锁和同步器的框架,使用A...

长头发-dawn
今天
5
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部