前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >LinkedHashSet内部是如何工作的(翻译)

LinkedHashSet内部是如何工作的(翻译)

作者头像
用户3579639
发布于 2018-10-22 06:53:24
发布于 2018-10-22 06:53:24
1K00
代码可运行
举报
运行总次数:0
代码可运行

LinkedHashSetHashSet的一个“扩展版本”,HashSet并不管什么顺序,不同的是LinkedHashSet会维护“插入顺序”。HashSet内部使用HashMap对象来存储它的元素,而LinkedHashSet内部使用LinkedHashMap对象来存储和处理它的元素。这篇文章,我们将会看到LinkedHashSet内部是如何运作的及如何维护插入顺序的。

我们首先着眼LinkedHashSet的构造函数。在LinkedHashSet类中一共有4个构造函数。这些构造函数都只是简单地调用父类构造函数(如HashSet类的构造函数)。 下面看看LinkedHashSet的构造函数是如何定义的。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
//Constructor - 1
 
public LinkedHashSet(int initialCapacity, float loadFactor)
{
      super(initialCapacity, loadFactor, true);              //Calling super class constructor
}
 
//Constructor - 2
 
public LinkedHashSet(int initialCapacity)
{
        super(initialCapacity, .75f, true);             //Calling super class constructor
}
 
//Constructor - 3
 
public LinkedHashSet()
{
        super(16, .75f, true);                //Calling super class constructor
}
 
//Constructor - 4
 
public LinkedHashSet(Collection<? extends E> c)
{
        super(Math.max(2*c.size(), 11), .75f, true);          //Calling super class constructor
        addAll(c);
}

在上面的代码片段中,你可能注意到4个构造函数调用的是同一个父类的构造函数。这个构造函数(父类的,译者注)是一个包内私有构造函数(见下面的代码,HashSet的构造函数没有使用public公开,译者注),它只能被LinkedHashSet使用。 这个构造函数需要初始容量,负载因子和一个boolean类型的哑值(没有什么用处的参数,作为标记,译者注)等参数。这个哑参数只是用来区别这个构造函数与HashSet的其他拥有初始容量和负载因子参数的构造函数,下面是这个构造函数的定义,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
HashSet(int initialCapacity, float loadFactor, boolean dummy)
{
        map = new LinkedHashMap<>(initialCapacity, loadFactor);
}

显然,这个构造函数内部初始化了一个LinkedHashMap对象,这个对象恰好被LinkedHashSet用来存储它的元素。

LinkedHashSet并没有自己的方法,所有的方法都继承自它的父类HashSet,因此,对LinkedHashSet的所有操作方式就好像对HashSet操作一样。 唯一的不同是内部使用不同的对象去存储元素。在HashSet中,插入的元素是被当做HashMap的键来保存的,而在LinkedHashSet中被看作是LinkedHashMap的键。 这些键对应的值都是常量PRESENT(PRESENT是HashSet的静态成员变量,译者注)。 可以参考How HashSet works internally in Java.

LinkedHashSet是如何维护插入顺序的

LinkedHashSet使用LinkedHashMap对象来存储它的元素,插入到LinkedHashSet中的元素实际上是被当作LinkedHashMap的键保存起来的。 LinkedHashMap的每一个键值对都是通过内部的静态类Entry<K, V>实例化的。这个 Entry<K, V>类继承了HashMap.Entry类。这个静态类增加了两个成员变量, beforeafter来维护LinkedHasMap元素的插入顺序。这两个成员变量分别指向前一个和后一个元素,这让LinkedHashMap也有类似双向链表的表现。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private static class Entry<K,V> extends HashMap.Entry<K,V>
{
        // These fields comprise the doubly linked list used for iteration.
        Entry<K,V> before, after;
 
        Entry(int hash, K key, V value, HashMap.Entry<K,V> next) {
            super(hash, key, value, next);
        }
}

从上面代码看到的LinkedHashMap内部类的前面两个成员变量——beforeafter负责维护LinkedHashSet的插入顺序。LinkedHashMap定义的成员变量header保存的是 这个双向链表的头节点。header的定义就像下面这样,

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
private transient Entry<K,V> header;        //Stores the head of the doubly linked list

In LinkedHashMap, the same set of Entry objects (rather references to Entry objects) are arranged in two different manner. One is the HashMap and another one is Doubly linked list. The Entry objects just sit on heap memory, unaware of that they are part of two different data structures.

接下来看一个例子就知道LinkedHashSet内部是如何工作的了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
public class LinkedHashSetExample
{
    public static void main(String[] args)
    {
        //Creating LinkedHashSet
 
        LinkedHashSet<String> set = new LinkedHashSet<String>();
 
        //Adding elements to LinkedHashSet
 
        set.add("BLUE");
 
        set.add("RED");
 
        set.add("GREEN");    
 
        set.add("BLACK");
    }
}

下面的图片展示了这个程序是如何运行的。

如果你知道LinkedHashMap内部是如何工作的,就非常容易明白LinkedHashSet内部是如何工作的。看一遍LinkedHashSetLinkedHashMap的源码, 你就能够准确地理解在JavaLinkedHashSet内部是如何工作的。

原文链接:How LinkedHashSet Works Internally In Java

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
(49) 剖析LinkedHashMap / 计算机程序的思维逻辑
之前我们介绍了Map接口的两个实现类HashMap和TreeMap,本节来介绍另一个实现类LinkedHashMap。它是HashMap的子类,但可以保持元素按插入或访问有序,这与TreeMap按键排序不同。 按插入有序容易理解,按访问有序是什么意思呢?这两个有序有什么用呢?内部是怎么实现的呢?本节就来探讨这些问题。从用法开始。 用法 基本概念 LinkedHashMap是HashMap的子类,但内部还有一个双向链表维护键值对的顺序,每个键值对既位于哈希表中,也位于这个双向链表中。 LinkedHashM
swiftma
2018/01/31
5430
(49)  剖析LinkedHashMap / 计算机程序的思维逻辑
HashSet源码剖析
set之所以没有放到和Collection接口一块学习是因为set接口底层实现的还是Map接口。他只是相当于在map接口上做了一次封装。
用户11097514
2024/05/30
860
HashSet源码剖析
Java集合框架之LinkedHashSet详解
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
喵手
2023/11/17
4080
Java集合框架之LinkedHashSet详解
死磕 java集合之LinkedHashSet源码分析
上一节我们说HashSet中的元素是无序的,那么有没有什么办法保证Set中的元素是有序的呢?
彤哥
2019/07/08
3460
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
海外geeksforgeeks网站画了这么一张Set集合的层次结构图,基本把Set集合涉及的常用类关系给标明了。
JavaSouth南哥
2024/08/15
2042
赶快收藏!全网最佳Set集合详解:HashSet、TreeSet!
HashSet 和 LinkedHashSet 源码分析,竟如此简单!
HashSet是一个可存储不重复元素的容器,底层实现依赖 HashMap ,所以在添加,删除,查找元素时的时间复杂度均为 O(1).
Java技术栈
2020/03/05
3790
集合系列 Set(七):LinkedHashSet
LinkedHashSet 继承了 HashSet,在此基础上维护了元素的插入顺序。
陈树义
2019/08/29
3040
基于LinkedHashMap实现LRU缓存调度算法原理及应用
在Android中实用LRU+软引用(弱引用)的方法来缓存图片,可以减少内存溢出的情况。
用户7353950
2022/05/11
3150
集合系列 Set(六):HashSet
HashSet 是 Set 集合的哈希实现,其继承了 AbstractSet 抽象类,并实现了 Set 接口。
陈树义
2019/08/29
4010
Java集合详解5:深入理解LinkedHashMap和LRU缓存
《Java集合详解系列》是我在完成夯实Java基础篇的系列博客后准备开始写的新系列。
Java技术江湖
2019/10/11
1.5K0
四大集合20连问,抗住!
业务开发究竟要使用LinkedList还是ArrayList?ArrayList查询性能更高,但LinkedList插入、删除效率更高。
JavaSouth南哥
2024/10/28
1800
四大集合20连问,抗住!
Java集合详解7:一文搞清楚HashSet,TreeSet与LinkedHashSet的异同
《Java集合详解系列》是我在完成夯实Java基础篇的系列博客后准备开始写的新系列。
Java技术江湖
2019/10/12
5780
Java Review - LinkedHashMap & LinkedHashSet 源码解读
Java Review - HashMap & HashSet 源码解读 中我们讲了HashSet和HashMap 。 那同样的套路 , LinkedHashSet和LinkedHashMap在Java里也有着相同的实现,LinkedHashSet仅仅是对LinkedHashMap做了一层包装,也就是说LinkedHashSet里面有一个LinkedHashMap(适配器模式)。
小小工匠
2021/11/17
3310
Java Review - LinkedHashMap & LinkedHashSet 源码解读
【Java入门提高篇】Day29 Java容器类详解(十一)LinkedHashSet详解
  当当当当当当当,本来打算出去浪来着,想想还是把这个先一起写完吧,毕竟这篇的主角跟我一样是一个超级偷懒的角色——LinkedHashSet,有多偷懒?看完你就知道了。
弗兰克的猫
2018/08/11
4220
【Java入门提高篇】Day29 Java容器类详解(十一)LinkedHashSet详解
【深入理解java集合系列】LinkedHashSet实现原理
LinkedHashSet是具有可预知迭代顺序的Set接口的哈希表和链接列表实现。此实现与HashSet的不同之处在于,后者维护着一个运行于所有条目的双重链接列表。此链接列表定义了迭代顺序,该迭代顺序可为插入顺序或是访问顺序。
爱笑的架构师
2020/09/24
1.2K0
JDK1.8源码(十)——java.util.LinkedHashSet类
  同 HashSet 与 HashMap 的关系一样,本篇博客所介绍的 LinkedHashSet 和 LinkedHashMap 也是一致的。在 JDK 集合框架中,类似 Set 集合通常都是由对应的 Map 类集合来实现的(TreeSet 和 TreeMap 同理),这里很重要的一个理论就是:Set 类集合是不允许重复的,而 Map 类集合的 key 也是不允许重复的,所以通常很容易就用 Map 类集合实现了 Set 类集合。
IT可乐
2018/12/19
5170
手撕包菜_handlecpuacceleration
LinkedHashSet 能够维护元素插入集合的顺序,在遍历时,按照此顺序进行遍历。
全栈程序员站长
2022/11/04
1790
LinkedHashMap 底层分析
众所周知 HashMap 是一个无序的 Map,因为每次根据 key 的 hashcode 映射到 Entry 数组上,所以遍历出来的顺序并不是写入的顺序。
爱明依
2022/04/01
2670
理解LinkedHashMap
LinkedHashMap是HashMap的一个子类,它保留插入的顺序,如果需要输出的顺序和输入时的相同,那么就选用LinkedHashMap。
大道七哥
2019/09/10
5610
理解LinkedHashMap
【145期】考考基础部分,谈谈Java集合中HashSet的原理及常用方法
HashSet是Java集合Set的一个实现类,Set是一个接口,其实现类除HashSet之外,还有TreeSet,并继承了Collection,HashSet集合很常用,同时也是程序员面试时经常会被问到的知识点,下面是结构图
良月柒
2021/03/09
3030
【145期】考考基础部分,谈谈Java集合中HashSet的原理及常用方法
推荐阅读
相关推荐
(49) 剖析LinkedHashMap / 计算机程序的思维逻辑
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
查看详情【社区公告】 技术创作特训营有奖征文