资讯专栏INFORMATION COLUMN

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

PiscesYE / 1917人阅读

摘要:下面看看的构造函数是如何定义的。的每一个键值对都是通过内部的静态类实例化的。如果你知道内部是如何工作的,就非常容易明白内部是如何工作的。

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的静态成员变量,译者注)。
可以参考How HashSet works internally in Java.

LinkedHashSet是如何维护插入顺序的

LinkedHashSet使用LinkedHashMap对象来存储它的元素,插入到LinkedHashSet中的元素实际上是被当作LinkedHashMap的键保存起来的。
LinkedHashMap的每一个键值对都是通过内部的静态类Entry实例化的。这个 Entry类继承了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");
    }
}

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

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

原文链接:How LinkedHashSet Works Internally In Java

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/65565.html

相关文章

  • Java编程基础18——集合(Set集合)

    摘要:并把最终的随机数输出到控制台。方法,在集合中如何存储元素取决于方法的返回值返回,集合中只有一个元素。创建集合对象,传入比较器。 1_HashSet存储字符串并遍历 A:Set集合概述及特点 通过API查看即可 B:案例演示 HashSet存储字符串并遍历 import java.util.HashSet; public class Demo1_HashSet { p...

    SexySix 评论0 收藏0
  • 第十一章 持有对象

    摘要:允许从任一方向来遍历对象,并在遍历迭代过程中进行修改该对象,还能获得迭代器的当前位置。这个构造函数是将返回了一个对象给,这也是的存储实现原理。 一、容器产生的原因   1.数组的缺点:大小一旦给定就无法更改,除非复制到一个新的数组中,开销大;而容器类都可以自动地调整自己的尺寸。  2.容器功能的多样性:容器可以实现各种不同要求,如按不同依据将元素进行排序或者保证容器内无重复元素等等。关...

    archieyang 评论0 收藏0
  • Java™ 教程(Set接口)

    Set接口 Set是一个不能包含重复元素的Collection,它模拟了数学集抽象,Set接口仅包含从Collection继承的方法,并添加禁止重复元素的限制,Set还为equals和hashCode操作的行为添加了一个更强的契约,允许Set实例有意义地进行比较,即使它们的实现类型不同,如果两个Set实例包含相同的元素,则它们是相等的。 Java平台包含三个通用的Set实现:HashSet、Tre...

    Apollo 评论0 收藏0
  • Java 集合 Set

    摘要:当复制集合中的所有元素来创建新的集合时,要求集合中的所有元素必须是同一个枚举类的枚举值各实现类的性能分析的性能总比好,特别是最常用的添加查询元素等操作。因为需要额外的红黑树算法来维护集合元素的次序。在创建时进行,以防对集合的意外非同步访问 HashSet 大多时候使用Set集合时就是使用HashSet实现类。HashSet按Hash算法来存储集合中的元素,因此具有很好的存取和查找性能 ...

    verano 评论0 收藏0
  • [学习笔记-Java集合-10] Set - LinkedHashSet源码分析

    摘要:就有这个功能,它是怎么实现有序的呢源码分析继承自,让我们直接上源码来看看它们有什么不同。是有序的,它是按照插入的顺序排序的。所以,是不支持按访问顺序对元素排序的,只能按插入顺序排序。 介绍 上一节我们说HashSet中的元素是无序的,那么有没有什么办法保证Set中的元素是有序的呢? 答案是当然可以。 LinkedHashSet就有这个功能,它是怎么实现有序的呢? 源码分析 Linked...

    ThreeWords 评论0 收藏0

发表评论

0条评论

PiscesYE

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<