Java中LinkedHashSet、LinkedHashMap源码详解

 更新时间:2023年09月05日 10:56:44   作者:颜狗备忘录  
这篇文章主要介绍了Java中LinkedHashSet、LinkedHashMap源码详解,LinkedHashMap是一个以双向链表的方式将Entry节点链接起来的HashMap子类,它在HashMap的基础上实现了更多的功能,具有顺序存储和遍历的特性,需要的朋友可以参考下

1.LinkedHashSet、LinkedHashMap总结

  • LinkedHashSet底层实现为LinkedHashMap
  • 数据结构为数组+双链表/红黑树(当数组长度不小于64,链表长度不小于8,该链表转成树结构)
  • 线程不安全
  • 根据插入顺序进行排序

备注:

红黑树(特殊的平衡二叉树)5大特性:

  1. 每个节点或者是黑色,或者是红色。
  2. 根节点是黑色。
  3. 每个叶子节点(NIL)是黑色。 [注意:这里叶子节点,是指为空(NIL或NULL)的叶子节点!]
  4. 如果一个节点是红色的,则它的子节点必须是黑色的。
  5. 从一个节点到该节点的子孙节点的所有路径上包含相同数目的黑节点。

2.分点详解

2.1 LinkedHashSet

2.1.1 继承实现情况

在这里插入图片描述

2.1.2 构造方法

//1.无参构造方法
public LinkedHashSet() {
		/**调用父类HashSet的构造方法,dummy只是为了重载加的参数,没有具体含义
		HashSet(int initialCapacity, float loadFactor, boolean dummy) {
        	map = new LinkedHashMap<>(initialCapacity, loadFactor);
    	}
		**/
		//默认初始数组长度16,加载因子为0.75
        super(16, .75f, true);
    }
//2.有参构造方法,数组长度
public LinkedHashSet(int initialCapacity) {
        super(initialCapacity, .75f, true);
    }
//3.有参构造方法,数组长度及加载因子
public LinkedHashSet(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor, true);
    }

2.1.3 添加数据

使用父类HashSet的添加方法。

2.2 LinkedHashMap

2.2.1 继承实现情况

在这里插入图片描述

2.2.2 构造方法

调用父类HashMap的构造方法。

//此参数是元素排序,等于true的时候是按哈希值排序,等于false的时候是按插入顺序排序
final boolean accessOrder;
//1.无参构造方法
public LinkedHashMap() {
        super();
        accessOrder = false;
    }
//2.有参构造方法,数组长度
public LinkedHashMap(int initialCapacity) {
        super(initialCapacity);
        accessOrder = false;
    }
//3.有参构造方法,数组长度和加载因子
public LinkedHashMap(int initialCapacity, float loadFactor) {
        super(initialCapacity, loadFactor);
        accessOrder = false;
    }

2.2.3 扩容机制

新增元素使用父类HashMap的put方法,(关键点来了)LinkedHashMap重写了NewNode方法,使节点是一个双向链表节点。 HashMap的NewNode方法:

Node<K,V> newNode(int hash, K key, V value, Node<K,V> next) {
        return new Node<>(hash, key, value, next);
    }
//HashMap的内部类Node
static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;
        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }
        public final K getKey()        { return key; }
        public final V getValue()      { return value; }
        public final String toString() { return key + "=" + value; }
        public final int hashCode() {
            return Objects.hashCode(key) ^ Objects.hashCode(value);
        }
        public final V setValue(V newValue) {
            V oldValue = value;
            value = newValue;
            return oldValue;
        }
        public final boolean equals(Object o) {
            if (o == this)
                return true;
            if (o instanceof Map.Entry) {
                Map.Entry<?,?> e = (Map.Entry<?,?>)o;
                if (Objects.equals(key, e.getKey()) &&
                    Objects.equals(value, e.getValue()))
                    return true;
            }
            return false;
        }
    }

LinkedHashMap的newNode方法:

Node<K,V> newNode(int hash, K key, V value, Node<K,V> e) {
        LinkedHashMap.Entry<K,V> p =
            new LinkedHashMap.Entry<K,V>(hash, key, value, e);
        linkNodeLast(p);
        return p;
    }
//LinkedHashMap的内部类Entry<K,V> 
static class Entry<K,V> extends HashMap.Node<K,V> {
        Entry<K,V> before, after;
        Entry(int hash, K key, V value, Node<K,V> next) {
            super(hash, key, value, next);
        }
    }
//指针前后指向
private void linkNodeLast(LinkedHashMap.Entry<K,V> p) {
        LinkedHashMap.Entry<K,V> last = tail;
        tail = p;
        if (last == null)
            head = p;
        else {
            p.before = last;
            last.after = p;
        }
    }

到此这篇关于Java中LinkedHashSet、LinkedHashMap源码详解的文章就介绍到这了,更多相关LinkedHashSet、LinkedHashMap源码内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • Spring Boot常见外部配置文件方式详析

    Spring Boot常见外部配置文件方式详析

    这篇文章主要给大家介绍了关于Spring Boot常见外部配置文件方式的相关资料,文中通过示例代码介绍的非常详细,对大家的学习或者使用Spring Boot具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
    2020-07-07
  • 浅析Java类和数据结构中常用的方法

    浅析Java类和数据结构中常用的方法

    下面小编就为大家带来一篇浅析Java类和数据结构中常用的方法。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
    2016-09-09
  • SpringEvents与异步事件驱动案例详解

    SpringEvents与异步事件驱动案例详解

    本文深入探讨了SpringBoot中的事件驱动架构,特别是通过Spring事件机制实现组件解耦和系统扩展性增强,介绍了事件的发布者、事件本身、事件监听器和事件处理器的概念,感兴趣的朋友跟随小编一起看看吧
    2024-09-09
  • JavaWeb JDBC + MySql 通讯录实现简单的增删改查功能案例详解

    JavaWeb JDBC + MySql 通讯录实现简单的增删改查功能案例详解

    这篇文章主要介绍了JavaWeb JDBC + MySql 通讯录实现简单的增删改查功能,结合具体案例形式详细分析了JavaWeb JDBC + MySql数据库连接、增删改查等相关操作技巧与注意事项,需要的朋友可以参考下
    2019-08-08
  • Java获取接口所有实现类的方式详解

    Java获取接口所有实现类的方式详解

    这篇文章主要介绍了Java获取接口所有实现类的方式详解,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2019-12-12
  • 详解Java对象序列化为什么要使用SerialversionUID

    详解Java对象序列化为什么要使用SerialversionUID

    这篇文章主要介绍了详解Java对象序列化为什么要使用SerialversionUID,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-11-11
  • Java超详细精讲数据结构之bfs与双端队列

    Java超详细精讲数据结构之bfs与双端队列

    广搜BFS的基本思想是: 首先访问初始点v并将其标志为已经访问。接着通过邻接关系将邻接点入队。然后每访问过一个顶点则出队。按照顺序,访问每一个顶点的所有未被访问过的顶点直到所有的顶点均被访问过。广度优先遍历类似与层次遍历
    2022-07-07
  • Springboot实现XSS漏洞过滤的示例代码

    Springboot实现XSS漏洞过滤的示例代码

    这篇文章主要介绍了Springboot实现XSS漏洞过滤的示例代码,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2021-01-01
  • Springboot结合Junit单元测试的实现

    Springboot结合Junit单元测试的实现

    Spring Boot框架通过整合JUnit,为开发者提供了便捷的单元测试支持,本文就来介绍Springboot结合Junit单元测试的实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2026-03-03
  • Java通过文件路径分隔符分割文件路径方式详解

    Java通过文件路径分隔符分割文件路径方式详解

    文章介绍了在处理Windows和Linux文件路径分隔符时的差异,强调直接用File.separator分割路径会因正则转义问题导致异常,建议用正则表达式“/|\\\”兼容两种系统进行路径分割
    2025-10-10

最新评论