LinkedHashMap 如何实现排序

news2024/11/15 15:34:02

目录

    • 一、LinkedHashMap
    • 二、排序实现
    • 三、代码片段分析

一、LinkedHashMap

    LinkedHashMap 是 Java 中的一个集合类,它是 HashMap 的一个子类,继承了 HashMap 的所有特性,并且在此基础上增加了一个双向链表来维护元素的插入顺序或者访问顺序。LinkedHashMap 通常用于需要保持插入顺序或者访问顺序的场合。

在这里插入图片描述
    
以下是 LinkedHashMap 的一些特点:

  • 顺序性:可以按照插入顺序或者访问顺序来迭代映射中的元素。
  • 性能:与 HashMap 类似,LinkedHashMap 在大多数情况下也提供了常数时间的性能。
  • 内存消耗:相比于 HashMap,LinkedHashMap 会消耗更多的内存,因为它需要额外的内存来维护双向链表。
  • LinkedHashMap 可以通过构造函数来指定是否按照插入顺序或者访问顺序来迭代:

默认情况下,LinkedHashMap 按照插入顺序来迭代。
如果在构造函数中传入 accessOrder 参数为 true,则按照访问顺序来迭代。
    

二、排序实现

    LinkedHashMap继承自HashMap并添加了一个双向链表来维护元素的插入顺序或访问顺序。以下是LinkedHashMap` 实现排序的原理和方法:

  1. 插入顺序排序:LinkedHashMap 默认按照元素的插入顺序进行排序。当元素被插入到 LinkedHashMap中时,它们会按照插入的顺序排列在双向链表中。即使后续元素的值被更新,它们在链表中的位置也不会改变,除非手动调用 remove 方法或者通过迭代器显式地删除元素。

  2. 访问顺序排序:可以通过在创建 LinkedHashMap实例时设置 accessOrder 参数为 true 来启用访问顺序排序。在这种模式下,每次通过 get 方法访问一个元素时,该元素会被移动到双向链表的末尾,从而保证最近访问的元素在链表的末尾。

  3. 按值排序:如果需要按照值对 LinkedHashMap 进行排序,可以使用 Collections.sort 方法或者 Java 8 引入的 Stream API。例如,可以使用 entrySet().stream().sorted(Map.Entry.comparingByValue()) 来对元素进行排序,然后通过 forEachOrderedcollect 方法将排序后的元素放入一个新的 LinkedHashMap 中。

  4. 自定义排序:如果 LinkedHashMap中的值不实现 Comparable 接口,可以通过提供一个自定义的 Comparator 来实现排序。例如,使用 Map.Entry.comparingByValue(Comparator.comparing(Player::getScore)) 来对包含自定义对象的 LinkedHashMap`进行排序。
        

三、代码片段分析

LinkedHashMap 按照元素的插入顺序进行排序的代码实现主要依赖于其内部的双向链表结构。以下是一些关键的代码片段,展示了 LinkedHashMap 如何维护插入顺序:

  1. 内部类 EntryLinkedHashMap 定义了一个内部类 Entry,继承自 HashMap.Node,并添加了两个新的引用 beforeafter 用于维护双向链表。

    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);
        }
    }
    
  2. 构造方法LinkedHashMap 提供了一个构造方法,允许设置 accessOrder 参数,默认为 false,表示按照插入顺序排序。

    public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
    }
    
  3. 插入操作:在 put 方法中,LinkedHashMap 调用 newNode 方法创建新的 Entry,并通过 linkNodeLast 方法将其添加到双向链表的末尾。

    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;
    }
    
  4. 维护链表linkNodeLast 方法将新节点添加到双向链表的末尾,并更新 headtail 指针。

    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;
        }
    }
    
  5. 迭代顺序LinkedHashMap 重写了 get 方法,在返回值之前,如果 accessOrderfalse(即按照插入顺序),则不需要调整链表。

    public V get(Object key) {
        Node<K,V> e;
        if ((e = getNode(hash(key), key)) == null)
            return null;
        if (accessOrder)
            afterNodeAccess(e);
        return e.value;
    }
    
  6. 迭代器LinkedHashMap 的迭代器会根据双向链表的顺序遍历元素,从而保证了迭代顺序与插入顺序相同。

    通过这些代码实现,LinkedHashMap能够按照元素的插入顺序进行排序。当 accessOrder 设置为 true 时,LinkedHashMap会转变为按照访问顺序排序,这通常是通过 afterNodeAccess 方法实现的,该方法会在访问元素时将其移动到链表的末尾。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2138253.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

java的内存分配和回收机制

Java 与 C之间有一堵由内存动态分配和垃圾收集技术所围成的高墙&#xff0c;墙外面的人想进去&#xff0c;墙里面的人却想出来。 概述 垃圾收集&#xff08;GC&#xff09;需要完成的三件事情&#xff1a; 哪些内存需要回收&#xff1f;什么时候回收&#xff1f;如何回收&am…

CloudXR 套件扩展 XR 工作流

NVIDIA为开发者提供了一个先进的平台&#xff0c;开发者可以在该平台上使用全新NVIDIA CloudXR 套件来创建可扩展、品牌化的定制扩展现实&#xff08;XR&#xff09;产品。 NVIDIA CloudXR 套件基于全新架构而打造&#xff0c;是扩展XR生态的重要工具。它为开发者、专业人士和…

高级 API 性能:着色器

着色器通过使您能够控制渲染过程的各个方面&#xff0c;在图形编程中发挥着关键作用。它们在 GPU 上运行&#xff0c;负责操作顶点、像素和其他数据。 常规着色器计算着色器像素渲染顶点着色器几何体、域和外壳着色器 常规着色器 这些提示适用于所有类型的着色器。 推荐 避…

[产品管理-10]:NPDP新产品开发 - 8 - 波士顿矩阵(当下与未来)在产品市场战略方面的应用

目录 一、波士顿矩阵 理论基础 产品类型划分 分析步骤 重要性 注意事项 二、波士顿矩阵的应用实例 示例背景 数据收集与准备 绘制波士顿矩阵 产品线分类 制定战略对策 一、波士顿矩阵&#xff1a;现在 VS 未来 波士顿矩阵理论&#xff0c;又称市场增长率-相对市场份…

读构建可扩展分布式系统:方法与实践04应用服务

1. 应用服务 1.1. 任何系统的核心都在于实现应用需求的特定业务逻辑 1.2. 服务是可扩展软件系统的核心 1.2.1. 它们将契约定义为一个API&#xff0c;向客户端声明它们的能力 1.3. 应用服务器高度依赖于编程语言&#xff0c;但通常都会提供多线程编程模型&#xff0c;允许服…

Ubuntu系统使用Docker部署Jupyter Notebook并实现笔记云同步

文章目录 前言1. 选择与拉取镜像2. 创建容器3. 访问Jupyter工作台4. 远程访问Jupyter工作台4.1 内网穿透工具安装4.2 创建远程连接公网地址4.3 使用固定二级子域名地址远程访问 前言 本文主要介绍如何在Ubuntu系统中使用Docker本地部署Jupyter Notebook&#xff0c;并结合cpol…

Netty(零散记录)

Netty&#xff1a; 1、Netty三种IO 2、Netty和Reactor的 1、Netty对Reactor的支持 Netty的线程模型时基于Reactor模型实现的&#xff0c;Netty对Reactor三种模式都有非常好的支持&#xff0c;并做了一定的改善&#xff0c;一般情况下&#xff0c;在服务端会采用主从架构模型…

Leetcode面试经典150题-739.每日温度

应读者私信要求&#xff0c;本题协商题目的具体内容 给定一个整数数组 temperatures &#xff0c;表示每天的温度&#xff0c;返回一个数组 answer &#xff0c;其中 answer[i] 是指对于第 i 天&#xff0c;下一个更高温度出现在几天后。如果气温在这之后都不会升高&#xff0…

计算机毕业设计 二手闲置交易系统的设计与实现 Java实战项目 附源码+文档+视频讲解

博主介绍&#xff1a;✌从事软件开发10年之余&#xff0c;专注于Java技术领域、Python人工智能及数据挖掘、小程序项目开发和Android项目开发等。CSDN、掘金、华为云、InfoQ、阿里云等平台优质作者✌ &#x1f345;文末获取源码联系&#x1f345; &#x1f447;&#x1f3fb; 精…

【目标检测数据集】厨房常见的水果蔬菜调味料数据集4910张39类VOC+YOLO格式

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;4910 标注数量(xml文件个数)&#xff1a;4910 标注数量(txt文件个数)&#xff1a;4910 标注…

SSH公私钥后门从入门到应急响应

目录 1. SSH公私钥与SSH公私钥后门介绍 1.1 SSH公私钥介绍 1.1.1 公钥和私钥的基本概念 1.1.2 SSH公私钥认证的工作原理(很重要) 1.2 SSH公私钥后门介绍 2. 如何在已拿下控制权限的主机创建后门 2.1 使用 Xshell 生成公钥与私钥 2.2 将公钥上传到被需要被植入后门的服务…

Qt_显示类控件

目录 一、QLabel 1、QLabel属性介绍 2、textFormat文本格式 3、pixmap标签图片 3.1 resizeEvent 4、QFrame边框 5、alignment文本对齐 6、wordWrap自动换行 7、indent设置缩进 8、margin设置边距 9、buddy设置伙伴 二、QLCDNumber 1、QLCDNumber属性介绍 2、实…

再次探讨最小生成树Prim算法

二次复习Prim算法时得到了一些新的启示。正常初次学算法时都特别注意代码&#xff0c;但是慢慢的发现&#xff0c;随着代码能力的增强&#xff0c;代码反而不是这么重要&#xff0c;重要的是算法的思路。既在自己的脑子中能有这个算法的图解。 下面展示一下二次学习的思路&…

秋韵虫趣.

文章目录 虫鸣概览虫坛文化蟀种纷呈中华蟋蟀宁阳蟋蟀刻点铁蟋长颚斗蟋 油葫芦棺头蟋中华灶蟋小素蟋树皮蟋蟀 花生大蟋斑腿针蟋其他鸣虫树蟋&#xff0c;又名竹蛉、邯郸梨片蟋&#xff0c;又名金钟、天蛉、绿蛣蛉、银琵琶凯纳奥蟋&#xff0c;又名石蛉&#xff0c;鳞蟋黄蛉蟋&am…

基于A2C与超启发式的航天器星载自主任务规划算法-笔记

1. Actor-Critic 模块 主要文件&#xff1a;AC.py, PolicyNet.py, ValueNet.py作用&#xff1a;该模块实现了 A2C&#xff08;Advantage Actor-Critic&#xff09;强化学习算法。其中&#xff0c;ActorCritic 类是核心&#xff0c;它同时管理策略网络&#xff08;Actor&#x…

misc合集(1)

[Week3] 这是一个压缩包 有密码&#xff0c;提示QmFzZUNURj8/Pz8/P0ZUQ2VzYUI base64解密是BaseCTF??????FTCesaB 猜测这应该是⼀个轴对称的密码 python ⽣成了密码字典&#xff0c;再通过 ARCHPR 进⾏字典爆破 lowercase abcdefghijklmnopqrstuvwxyz uppercase l…

Vue生命周期;Vue路由配置;vue网络请求;vue跨域处理

一&#xff0c;Vue生命周期 <template><div > <h1 click"changeText">{{ info }}</h1></div> </template><script> export default {name: HelloWorld,data(){return{info:"介绍组件生命周期"}},methods:{chang…

Android源码导入Android Studio

版权归作者所有&#xff0c;如有转发&#xff0c;请注明文章出处&#xff1a;https://cyrus-studio.github.io/blog/ 前言 需要先把 Android 源码编译一遍 然后执行下面指令就可以导入android源码了 关于 Android 源码编译可以参考这篇文章【LineageOS源码下载和编译&#xf…

GitLab CI_CD 从入门到实战笔记

第1章 认识GitLab CI/CD 1.3 GitLab CI/CD的几个基本概念 GitLab CI/CD由以下两部分构成。 &#xff08;1&#xff09;运行流水线的环境。它是由GitLab Runner提供的&#xff0c;这是一个由GitLab开发的开源软件包&#xff0c;要搭建GitLab CI/CD就必须安装它&#xff0c;因…

搜索二叉树BSTree的原理及实现

目录 一、简介 二、功能的实现 节点的实现 这里为什么模板参数采用的是K而不是T呢&#xff1f; 树体的实现 非递归版本 Insert函数 Find函数 Erase函数 递归版本 中序遍历 FindR InsertR EraseR 构造函数 析构函数 拷贝构造 赋值重载 一、简介 BSTree&#x…