HashSet 是 Set 集合的哈希实现,其继承了 AbstractSet 抽象类,并实现了 Set 接口。

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

原理

为了深入理解 HashSet 的原理,我们将从类成员变量、构造方法、核心方法两个方面逐一介绍。

类成员变量

// HashSet内部使用HashMap存储
private transient HashMap<E,Object> map;
// 存储在value上的值
private static final Object PRESENT = new Object();

从类成员变量我们可以知道,HashSet 内部使用 HashMap 存储,而 PRESENT 则是存储在所有 key 上的 value。因此对于 HashSet 来说,其所有 key 的 value 都相同。

构造方法

HashSet 一共有 5 个构造方法。

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);
}

可以看到构造方法传入的参数其实就是用于初始化 HashMap 对象,主要有:initialCapacity(初始大小)、loadFactor(扩容因子)。这几个构造参数内容并不复杂,这里就不细讲了。

这里有一个关键的细节,即第 5 个方法使用 LinkedHashMap 实现的,而不是用 HashMap 实现的。而我们后面要讲到的 LinkedHashSet 其实就是使用 LinkedHashMap 实现的,其保存了插入元素的顺序。

核心方法

对于 HashSet 来说,其核心的方法有:add、remove。

我们先看 add 方法。

public boolean add(E e) {
return map.put(e, PRESENT)==null;
}

可以看到 add 方法直接调用了 HashMap 对象的 put 方法。如果 Set 集合插入成功,那么就返回 true,否则返回 false。

接着我们看看 remove 方法。

public boolean remove(Object o) {
return map.remove(o)==PRESENT;
}

可以看到 remove 方法直接调用了 HashMap 对象的 remove 方法。如果删除成功,就返回 true,否则返回 false。

总结

HashSet 的源码也是非常简单了,其直接借用了 HashMap 的实现。所以如果你弄懂了 HashMap,那么 HashSet 自然不在话下了。

集合系列 Set(六):HashSet的更多相关文章

  1. Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例

    概要 这一章,我们对HashSet进行学习.我们先对HashSet有个整体认识,然后再学习它的源码,最后再通过实例来学会使用HashSet.内容包括:第1部分 HashSet介绍第2部分 HashSe ...

  2. 【转】Java 集合系列16之 HashSet详细介绍(源码解析)和使用示例--不错

    原文网址:http://www.cnblogs.com/skywang12345/p/3311252.html 概要 这一章,我们对HashSet进行学习.我们先对HashSet有个整体认识,然后再学 ...

  3. Java集合系列(三):HashSet、LinkedHashSet、TreeSet的使用方法及区别

    本篇博客主要讲解Set接口的三个实现类HashSet.LinkedHashSet.TreeSet的使用方法以及三者之间的区别. 注意:本文中代码使用的JDK版本为1.8.0_191 1. HashSe ...

  4. List、Set集合系列之剖析HashSet存储原理(HashMap底层)

    目录 List接口 1.1 List接口介绍 1.2 List接口中常用方法 List的子类 2.1 ArrayList集合 2.2 LinkedList集合 Set接口 3.1 Set接口介绍 Se ...

  5. java集合系列——Set之HashSet和TreeSet介绍(十)

    一.Set的简介 Set是一个不包含重复元素的 collection.更确切地讲,set 不包含满足 e1.equals(e2) 的元素.对 e1 和 e2,并且最多包含一个为 null 的元素. S ...

  6. 【Java集合系列四】HashSet和LinkedHashSet解析

    2017-07-29 16:58:13 一.简介 1.Set概念 Set可以理解为集合,非常类似数据概念中的集合,集合三大特征:1.确定性:2.互异性:3.无序性,因此Set实现类也有类似的特征. 2 ...

  7. 【Java集合系列】目录

    2017-07-29 13:49:40 一.Collection的全局继承关系 二.系列文章 [Java集合系列一]ArrayList解析 备注: 1.ArrayList本质上就是一个数组,所有对外提 ...

  8. Java 集合系列目录(Category)

    下面是最近总结的Java集合(JDK1.6.0_45)相关文章的目录. 01. Java 集合系列01之 总体框架 02. Java 集合系列02之 Collection架构 03. Java 集合系 ...

  9. Java 集合系列 16 HashSet

    java 集合系列目录: Java 集合系列 01 总体框架 Java 集合系列 02 Collection架构 Java 集合系列 03 ArrayList详细介绍(源码解析)和使用示例 Java ...

  10. 【集合系列】- 深入浅出的分析 Set集合

    一.摘要 关于 Set 接口,在实际开发中,其实很少用到,但是如果你出去面试,它可能依然是一个绕不开的话题. 言归正传,废话咱们也不多说了,相信使用过 Set 集合类的朋友都知道,Set集合的特点主要 ...

随机推荐

  1. jqurey(尺寸,css操作,效果,遍历)

    尺寸: height():设置或返回元素的高度(不包括内边距.边框或外边距). width():设置或返回元素的宽度(不包括内边距.边框或外边距). 例如: $("#box").h ...

  2. 磁盘分区(GPT)

    右击 我的电脑 → 管理 → 磁盘管理 (对磁盘1进行分区)右击 磁盘1 → 初始化 磁盘1 右击 磁盘1白色部分 → 新建磁盘分区 先创建主分区(主分区最多创建4个,扩展分区最多1个) 输入分区大小 ...

  3. 一次使用pip后的总结

    pip 常用命令及搭配操作 一 .当安装了多个版本python的时候,表示用pythonx 的pip 进行: 1.pythonx -m pip install + 包名 装 包 2.pythonx - ...

  4. 大数据学习笔记——Java篇之集合框架(ArrayList)

    Java集合框架学习笔记 1. Java集合框架中各接口或子类的继承以及实现关系图: 2. 数组和集合类的区别整理: 数组: 1. 长度是固定的 2. 既可以存放基本数据类型又可以存放引用数据类型 3 ...

  5. LNMP-Nginx配置不记录静态文件、过期时间

    用户访问web网站,通常日志文件会记录很多web站点上的一些静态文件信息,如果长期不处理,日志文件会越来越大,占用的系统资源也越大,此时就需要我们配置不记录静态文件和过期时间,减少日志文件记录过多不必 ...

  6. poj 1741 Tree (树的分治)

    Tree Time Limit: 1000MS   Memory Limit: 30000K Total Submissions: 30928   Accepted: 10351 Descriptio ...

  7. 《Java基础知识》Java变量的声明、初始化和作用域

    一.Java变量的声明 在 Java 程序设计中,每个声明的变量都必须分配一个类型.声明一个变量时,应该先声明变量的类型,随后再声明变量的名字.下面演示了变量的声明方式. double salary; ...

  8. vue hover如何触发事件?

    vue中并没有 @hover 事件,但是可以使用 @mouseenter 和 @mouseleave 来模拟hover操作.

  9. vue.config.js的常用配置

    const path = require('path') const glob = require('glob') const resolve = (dir) => path.join(__di ...

  10. 15.junit测试类使用及注解

    1.junit简介 JUnit是一个Java语言的单元测试框架,可以大大缩短你的测试时间和准确度.多数Java的开发环境都已经集成了JUnit作为单元测试的工具. 2.实现junitDemo示例 2. ...