死磕 java集合之LinkedHashSet源码分析
问题
(1)LinkedHashSet的底层使用什么存储元素?
(2)LinkedHashSet与HashSet有什么不同?
(3)LinkedHashSet是有序的吗?
(4)LinkedHashSet支持按元素访问顺序排序吗?
简介
上一节我们说HashSet中的元素是无序的,那么有没有什么办法保证Set中的元素是有序的呢?
答案是当然可以。
我们今天的主角LinkedHashSet就有这个功能,它是怎么实现有序的呢?让我们来一起学习吧。
源码分析
LinkedHashSet继承自HashSet,让我们直接上源码来看看它们有什么不同。
package java.util;
// LinkedHashSet继承自HashSet
public class LinkedHashSet<E>
extends HashSet<E>
implements Set<E>, Cloneable, java.io.Serializable {
private static final long serialVersionUID = -2851667679971038690L;
// 传入容量和装载因子
public LinkedHashSet(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor, true);
}
// 只传入容量, 装载因子默认为0.75
public LinkedHashSet(int initialCapacity) {
super(initialCapacity, .75f, true);
}
// 使用默认容量16, 默认装载因子0.75
public LinkedHashSet() {
super(16, .75f, true);
}
// 将集合c中的所有元素添加到LinkedHashSet中
// 好奇怪, 这里计算容量的方式又变了
// HashSet中使用的是Math.max((int) (c.size()/.75f) + 1, 16)
// 这一点有点不得其解, 是作者偷懒?
public LinkedHashSet(Collection<? extends E> c) {
super(Math.max(2*c.size(), 11), .75f, true);
addAll(c);
}
// 可分割的迭代器, 主要用于多线程并行迭代处理时使用
@Override
public Spliterator<E> spliterator() {
return Spliterators.spliterator(this, Spliterator.DISTINCT | Spliterator.ORDERED);
}
}
完了,结束了,就这么多,这是全部源码了,真的。
可以看到,LinkedHashSet中一共提供了5个方法,其中4个是构造方法,还有一个是迭代器。
4个构造方法都是调用父类的super(initialCapacity, loadFactor, true);这个方法。
这个方法长什么样呢?
还记得我们上一节说过一个不是public的构造方法吗?就是它。
// HashSet的构造方法
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
如上所示,这个构造方法里面使用了LinkedHashMap来初始化HashSet中的map。
现在这个逻辑应该很清晰了,LinkedHashSet继承自HashSet,它的添加、删除、查询等方法都是直接用的HashSet的,唯一的不同就是它使用LinkedHashMap存储元素。
那么,开篇那几个问题是否能回答了呢?
总结
(1)LinkedHashSet的底层使用LinkedHashMap存储元素。
(2)LinkedHashSet是有序的,它是按照插入的顺序排序的。
彩蛋
通过上面的学习,我们知道LinkedHashSet底层使用LinkedHashMap存储元素,而LinkedHashMap是支持按元素访问顺序遍历元素的,也就是可以用来实现LRU的,还记得吗?传送门【死磕 java集合之LinkedHashMap源码分析】
那么,LinkedHashSet支持按元素访问顺序排序吗?
让我们一起来分析下。
首先,LinkedHashSet所有的构造方法都是调用HashSet的同一个构造方法,如下:
// HashSet的构造方法
HashSet(int initialCapacity, float loadFactor, boolean dummy) {
map = new LinkedHashMap<>(initialCapacity, loadFactor);
}
然后,通过调用LinkedHashMap的构造方法初始化map,如下所示:
public LinkedHashMap(int initialCapacity, float loadFactor) {
super(initialCapacity, loadFactor);
accessOrder = false;
}
可以看到,这里把accessOrder写死为false了。
所以,LinkedHashSet是不支持按访问顺序对元素排序的,只能按插入顺序排序。
欢迎关注我的公众号“彤哥读源码”,查看更多源码系列文章, 与彤哥一起畅游源码的海洋。

死磕 java集合之LinkedHashSet源码分析的更多相关文章
- 死磕 java集合之DelayQueue源码分析
问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...
- 死磕 java集合之PriorityBlockingQueue源码分析
问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...
- 死磕 java集合之PriorityQueue源码分析
问题 (1)什么是优先级队列? (2)怎么实现一个优先级队列? (3)PriorityQueue是线程安全的吗? (4)PriorityQueue就有序的吗? 简介 优先级队列,是0个或多个元素的集合 ...
- 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计
问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...
- 死磕 java集合之ConcurrentHashMap源码分析(三)
本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...
- 死磕 java集合之ArrayDeque源码分析
问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...
- 【死磕 Java 集合】— ConcurrentSkipListMap源码分析
转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...
- 死磕 java集合之LinkedList源码分析
问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedL ...
- 死磕 java集合之ConcurrentSkipListSet源码分析——Set大汇总
问题 (1)ConcurrentSkipListSet的底层是ConcurrentSkipListMap吗? (2)ConcurrentSkipListSet是线程安全的吗? (3)Concurren ...
随机推荐
- yii2.0 app上集成支付宝支付
1.首先从支付宝官网下载支付宝app支付sdk 地址 : https://doc.open.alipay.com/docs/doc.htm?spm=a219a.7629140.0.0.hLEa5O&a ...
- 使用Spring MVC测试Spring Security Oauth2 API
不是因为看到希望了才去坚持,而坚持了才知道没有希望. 前言 在Spring Security源码分析十一:Spring Security OAuth2整合JWT和Spring Boot 2.0 整合 ...
- selenium自动化测试资源整理(含所有版本chrome、chromedriver、firefox下载链接)
今天把手头有的一些关于selenium测试的资源整理了一下,分享出来. 1. 所有版本chrome下载 是不是很难找到老版本的chrome?博主收集了几个下载chrome老版本的网站,其中哪个下载的是 ...
- [爬虫]scrapy框架
Scrapy介绍 Scrapy是一个为了爬取网站数据,提取结构性数据而编写的应用框架. 可以应用在包括数据挖掘,信息处理或存储历史数据等一系列的程序中. 所谓网络爬虫,就是一个在网上到处或定向抓取数据 ...
- Java Fork/Join 框架
简介 从JDK1.7开始,Java提供Fork/Join框架用于并行执行任务,它的思想就是讲一个大任务分割成若干小任务,最终汇总每个小任务的结果得到这个大任务的结果. 这种思想和MapReduce很像 ...
- python常见的报错提示
在运行或编写一个程序时常会遇到错误异常,这时python会给你一个错误提示类名,告诉出现了什么样的问题(Python是面向对象语言,所以程序抛出的异常也是类).能很好的理解这些错误提示类名所代表的意思 ...
- java quartz 计算近20次执行时间
/** * * @desc 计算表达式近20次时间 * @auth josnow * @date 2017年5月31日 下午12:16:25 * @param cron * @return */ pu ...
- Eigen实现坐标转换
(<视觉SLAM十四讲>第三讲习题7)设有小萝卜一号和二号在世界坐标系中.一号位姿q1 = [0.35, 0.2, 0.3, 0.1],t1=[0.3, 0.1, 0.1].二号位姿q2= ...
- Eclipse连接Hadoop集群及WordCount实践
声明:作者原创,转载注明出处. 作者:帅气陈吃苹果 一.环境准备 1.JDK安装与配置 2.Eclipse下载 下载解压即可,下载地址:https://pan.baidu.com/s/1i51UsVN ...
- Java进阶篇之十五 ----- JDK1.8的Lambda、Stream和日期的使用详解(很详细)
前言 本篇主要讲述是Java中JDK1.8的一些新语法特性使用,主要是Lambda.Stream和LocalDate日期的一些使用讲解. Lambda Lambda介绍 Lambda 表达式(lamb ...