博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
LinkedHashSet内部是如何工作的(翻译)
阅读量:5948 次
发布时间:2019-06-19

本文共 3267 字,大约阅读时间需要 10 分钟。

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

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

下面看看LinkedHashSet的构造函数是如何定义的。

//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
c){ super(Math.max(2*c.size(), 11), .75f, true); //Calling super class constructor addAll(c);}

在上面的代码片段中,你可能注意到4个构造函数调用的是同一个父类的构造函数。这个构造函数(父类的,译者注)是一个包内私有构造函数(见下面的代码,HashSet的构造函数没有使用public公开,译者注),它只能被LinkedHashSet使用。

这个构造函数需要初始容量,负载因子和一个boolean类型的哑值(没有什么用处的参数,作为标记,译者注)等参数。这个哑参数只是用来区别这个构造函数与HashSet的其他拥有初始容量和负载因子参数的构造函数,下面是这个构造函数的定义,

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的静态成员变量,译者注)。
可以参考

LinkedHashSet是如何维护插入顺序的

LinkedHashSet使用LinkedHashMap对象来存储它的元素,插入到LinkedHashSet中的元素实际上是被当作LinkedHashMap的键保存起来的。

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

private static class Entry
extends HashMap.Entry
{ // These fields comprise the doubly linked list used for iteration. Entry
before, after; Entry(int hash, K key, V value, HashMap.Entry
next) { super(hash, key, value, next); }}

从上面代码看到的LinkedHashMap内部类的前面两个成员变量——beforeafter负责维护LinkedHashSet的插入顺序。LinkedHashMap定义的成员变量header保存的是

这个双向链表的头节点。header的定义就像下面这样,

private transient Entry
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内部是如何工作的了。

public class LinkedHashSetExample{    public static void main(String[] args)    {        //Creating LinkedHashSet         LinkedHashSet
set = new LinkedHashSet
(); //Adding elements to LinkedHashSet set.add("BLUE"); set.add("RED"); set.add("GREEN"); set.add("BLACK"); }}

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

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

原文链接:

转载地址:http://dwdxx.baihongyu.com/

你可能感兴趣的文章
struct框架
查看>>
Deep Learning(深度学习)相关网站
查看>>
设置Eclipse编码方式
查看>>
分布式系统唯一ID生成方案汇总【转】
查看>>
并查集hdu1232
查看>>
oracle进行字符串拆分并组成数组
查看>>
100多个基础常用JS函数和语法集合大全
查看>>
Java8 lambda表达式10个示例
查看>>
innerHTML outerHTML innerText
查看>>
kafka安装教程
查看>>
go语言基础
查看>>
【Windows】字符串处理
查看>>
Spring(十八):Spring AOP(二):通知(前置、后置、返回、异常、环绕)
查看>>
CentOS使用chkconfig增加开机服务提示service xxx does not support chkconfig的问题解决
查看>>
微服务+:服务契约治理
查看>>
save
查看>>
Android DrawLayout + ListView 的使用(一)
查看>>
clear session on close of browser jsp
查看>>
关于吃掉物理的二次聚合无法实现的需要之旁门左道实现法
查看>>
mysql出现unblock with 'mysqladmin flush-hosts'
查看>>