问题

(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源码分析的更多相关文章

  1. 死磕 java集合之DelayQueue源码分析

    问题 (1)DelayQueue是阻塞队列吗? (2)DelayQueue的实现方式? (3)DelayQueue主要用于什么场景? 简介 DelayQueue是java并发包下的延时阻塞队列,常用于 ...

  2. 死磕 java集合之PriorityBlockingQueue源码分析

    问题 (1)PriorityBlockingQueue的实现方式? (2)PriorityBlockingQueue是否需要扩容? (3)PriorityBlockingQueue是怎么控制并发安全的 ...

  3. 死磕 java集合之PriorityQueue源码分析

    问题 (1)什么是优先级队列? (2)怎么实现一个优先级队列? (3)PriorityQueue是线程安全的吗? (4)PriorityQueue就有序的吗? 简介 优先级队列,是0个或多个元素的集合 ...

  4. 死磕 java集合之CopyOnWriteArraySet源码分析——内含巧妙设计

    问题 (1)CopyOnWriteArraySet是用Map实现的吗? (2)CopyOnWriteArraySet是有序的吗? (3)CopyOnWriteArraySet是并发安全的吗? (4)C ...

  5. 死磕 java集合之ConcurrentHashMap源码分析(三)

    本章接着上两章,链接直达: 死磕 java集合之ConcurrentHashMap源码分析(一) 死磕 java集合之ConcurrentHashMap源码分析(二) 删除元素 删除元素跟添加元素一样 ...

  6. 死磕 java集合之ArrayDeque源码分析

    问题 (1)什么是双端队列? (2)ArrayDeque是怎么实现双端队列的? (3)ArrayDeque是线程安全的吗? (4)ArrayDeque是有界的吗? 简介 双端队列是一种特殊的队列,它的 ...

  7. 【死磕 Java 集合】— ConcurrentSkipListMap源码分析

    转自:http://cmsblogs.com/?p=4773 [隐藏目录] 前情提要 简介 存储结构 源码分析 主要内部类 构造方法 添加元素 添加元素举例 删除元素 删除元素举例 查找元素 查找元素 ...

  8. 死磕 java集合之LinkedList源码分析

    问题 (1)LinkedList只是一个List吗? (2)LinkedList还有其它什么特性吗? (3)LinkedList为啥经常拿出来跟ArrayList比较? (4)我为什么把LinkedL ...

  9. 死磕 java集合之ConcurrentSkipListSet源码分析——Set大汇总

    问题 (1)ConcurrentSkipListSet的底层是ConcurrentSkipListMap吗? (2)ConcurrentSkipListSet是线程安全的吗? (3)Concurren ...

随机推荐

  1. 用python对比两张图片的不同

    from PIL import Image from PIL import ImageChops def compare_images(path_one, path_two, diff_save_lo ...

  2. Class path & Path

    Class path: 配置类文件 (配置完之后,在任何盘符下都可以访问该配置路径下的文件); Path: 配置可执行文件; Class path 配置时路径后面加分号与不加分号的区别 (当前路径与配 ...

  3. JFree图表

    ************************************************************************************* 使用JFree生成统计图片, ...

  4. Mui Webview下来刷新上拉加载实现

    有些事情经历过之后才会发现,原来再次之前我是如此的啥,因为是第一次做,毫无头绪,有时会想假如有个一demo就好了,那么就不会花费这么多的无用功了.今天使用mui 的webview实现了一个H5页面的上 ...

  5. Mybaits-plus实战(三)

    1. Mybaits-plus实战(三) 1.1. 特殊使用规则 1.1.1. Model逻辑删除 数据库对应实体类,继承Model类可以实现AR模式的sql语句操作,但这里需要注意的是,对逻辑删除, ...

  6. 1. CMake 系列 - 从零构建动态库和静态库

    目录 1. 文件目录结构 2. 库文件源代码 3. 编译生成库文件 1. 文件目录结构 首先创建如下目录结构: └── lib ├── build # ├── CMakeLists.txt └── s ...

  7. Java核心技术梳理-基础类库

    一.引言 Oracle为Java提供了丰富的基础类库,Java 8 提供了4000多个基础类库,熟练掌握这些基础类库可以提高我们的开发效率,当然,记住所有的API是不可能也没必要的,我们可以通过API ...

  8. 一起来学spring Cloud | 第一章:spring Cloud 与Spring Boot

    目前大家都在说微服务,其实微服务不是一个名字,是一个架构的概念,大家现在使用的基于RPC框架(dubbo.thrift等)架构其实也能算作一种微服务架构. 目前越来越多的公司开始使用微服务架构,所以在 ...

  9. shiro的DelegatingFilterProxy怎么找到ShiroFilterFactoryBean

    首先看到web.xml中的配置 <context-param> <param-name>contextConfigLocation</param-name> < ...

  10. 天津联通新兴ICT业务工程师面试经历

    此次是天津联通来我们学校进行校招宣讲,参加的人挺多的.一开始没打印成绩单,临时去打印的,然后排到我的时候以经快结束了 == 面试 首先当然是自我介绍啦,就巴拉巴拉了一堆自己的专业,学过什么跟职位相关的 ...