Java LinkedHashMap 类

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(268)   2023-06-26 07:54:18

Java中的LinkedHashMap用于存储键值对,非常类似于HashMap类。不同之处在于 LinkedHashMap 维护插入其中的元素的顺序,而 HashMap 是无序的。

在这个 Java 集合教程中,我们将了解 LinkedHashMap 类、它的方法、用例和其他重要细节。

1. LinkedHashMap层次结构

LinkedHashMap 类在 Java 中声明如下。它扩展了HashMap类并实现了Map接口。这里 'K' 是键的类型,'V' 是映射值到键的类型。

public class LinkedHashMap<K,V>
    extends HashMap<K,V>
    implements Map<K,V>
{
	//implementation
}

2. LinkedHashMap 特点

了解 Java LinkedHashMap 类的重要事项是:

  • 它存储的键值对类似于HashMap。
  • 它只包含唯一键。不允许重复键。
  • 它可能有一个 null 键和多个 null 值。
  • 它通过向内部管理的双向链表添加元素来维护插入其中的 K、V 对的顺序。

2.1.插入有序的LinkedHashMap

默认情况下,LinkedHashMap 是按插入顺序排列的。它在添加元素时维护元素的顺序。在遍历 LinkedHashMap 时,我们按照添加的确切顺序获得 KV 对。

LinkedHashMap<Integer, String> pairs = new LinkedHashMap<>();
        
pairs.put(1,  "A");
pairs.put(2,  "B");
pairs.put(3,  "C");
pairs.put(4,  "D");

pairs.forEach((key, value) -> {
    System.out.println("Key:"+ key + ", Value:" + value);
});

程序输出。

Key:1, Value:A
Key:2, Value:B
Key:3, Value:C
Key:4, Value:D

2.2.访问有序的 LinkedHashMap

在访问有序映射中,键根据上次使用 LinkedHashMap 的任何方法访问它们时的访问顺序进行排序。调用 put、putIfAbsent、get、getOrDefault、compute、computeIfAbsent、computeIfPresent 或 merge 方法会导致对相应条目的访问。

键按照从最近最少访问到最近最多访问的顺序排序,并构建 LRU 缓存。

为了创建访问顺序映射,LinkedHashMap 有一个特殊的构造函数参数。当设置为 true 时,LinkedHashMap 保持访问顺序。

//3rd parameter set access order
LinkedHashMap<Integer, String> pairs = new LinkedHashMap<>(2, .75f, true);

pairs.put(1,  "A");
pairs.put(2,  "B");
pairs.put(3,  "C");
pairs.put(4,  "D");

//Access 3rd pair
pairs.get(3);

//Access 1st pair
pairs.getOrDefault(2, "oops");

pairs.forEach((key, value) -> {
    System.out.println("Key:"+ key + ", Value:" + value);
});     

程序输出。

Key:1, Value:A
Key:4, Value:D
Key:3, Value:C
Key:2, Value:B

请注意最近访问的条目如何到达顺序末尾的输出。

3. LinkedHashMap 构造函数

LinkedHashMap 有五种类型的构造函数:

  1. LinkedHashMap():使用默认初始容量 (16) 和加载因子 (0.75) 初始化默认 LinkedHashMap 实现。
  2. LinkedHashMap(int capacity):使用指定的容量和负载因子 (0.75) 初始化 LinkedHashMap。
  3. LinkedHashMap(Map map):使用与指定映射相同的映射初始化 LinkedHashMap。
  4. LinkedHashMap(int capacity, float fillRatio):使用指定的初始容量和加载因子初始化 LinkedHashMap。
  5. LinkedHashMap(int capacity, float fillRatio, boolean Order): 初始化 LinkedHashMap 的容量和填充率,以及是否保持插入顺序或访问顺序。
    • 'true' 启用访问顺序。
    • 'false' 启用插入顺序。这是使用其他构造函数时的默认值行为。

4.LinkedHashMap方法

关于LinkedHashMap我们应该学习的重要方法如下:

  1. void clear():它从映射中删除所有键值对。
  2. void size():它返回此映射中存在的键值对的数量。
  3. void isEmpty():如果此映射不包含键值映射,则返回 true..
  4. boolean containsKey(Object key):如果地图中存在指定键,则返回 'true'
  5. boolean containsValue(Object key):如果指定值映射到映射中的至少一个键,则返回 'true'
  6. Object get(Object key):它检索由指定的key映射的value
  7. Object remove(Object key):它从映射中删除指定键的键值对(如果存在)。
  8. boolean removeEldestEntry(Map.Entry eldest):当地图从访问有序地图中删除其最老的条目时,它返回 'true'

4.1. Java LinkedHashMap 示例

用于演示 linkedhashmap 方法用法的 Java 程序。

import java.util.Iterator;
import java.util.LinkedHashMap;

public class LinkedHashMapExample 
{
    public static void main(String[] args) 
    {
        //3rd parameter set access order
        LinkedHashMap<Integer, String> pairs = new LinkedHashMap<>();
        
        pairs.put(1,  "A");
        pairs.put(2,  "B");
        pairs.put(3,  "C");
        
        String value = pairs.get(3);    //get method
        
        System.out.println(value);
        
        value = pairs.getOrDefault(5, "oops");  //getOrDefault method
        
        System.out.println(value);
        
        //Iteration example
        Iterator<Integer> iterator =  pairs.keySet().iterator();
        
        while(iterator.hasNext()) {
            Integer key = iterator.next();
            System.out.println("Key: " + key + ", Value: " + pairs.get(key));
        }
        
        //Remove example
        pairs.remove(3);
        System.out.println(pairs);
        
        System.out.println(pairs.containsKey(1));    //containsKey method   
        
        System.out.println(pairs.containsValue("B"));    //containsValue method   
    }
}

程序输出。

C
oops
Key: 1, Value: A
Key: 2, Value: B
Key: 3, Value: C
{1=A, 2=B}
true
true

5. LinkedHashMap 用例

几乎所有需要使用HashMap的情况下,我们都可以使用LinkedHashMap。在功能方面,它可以非常透明地替代 HashMap。

此外,LinkedHashMap 维护插入顺序,这在我们想要维护添加到 Map 的对的顺序时非常有用。

访问有序的 LinkedHashMap 为创建 LRU 缓存 功能提供了一个很好的起点,方法是重写 removeEldestEntry() 方法以在新映射添加到地图。这使您可以使用您定义的某些条件使数据过期。

6. LinkedHashMap 性能

HashMap 和 LinkedHashMap 以常量时间性能执行添加、删除和包含的基本操作。 LinkedHashMap 比 HashMap 性能差一些,因为它要维护一个双向链表,而 HashMap 只维护一个链表。

另一方面,在 LinkedHashMap 的情况下循环 Map 比 HashMap 稍微快一些,因为所需的时间仅与“大小”成正比。在 HashMap 的情况下,迭代性能与“大小 + 容量”成正比。

7. LinkedHashMap 中的并发

HashMap 和 LinkedHashMap 都不是线程安全的,这意味着我们不能直接在多线程应用程序中使用它们来获得一致的结果。我们应该使用 Collections.synchronizedMap(Map map) 方法显式同步它们。

Map<Integer, Integer> numbers = Collections.synchronizedMap(new LinkedHashMap<>());

Map<Integer, Integer> numbers = Collections.synchronizedMap(new HashMap<>());

在 HashMap 的情况下,使用 ConcurrentHashMap 是更可取的,因为它提供了更高的并发度。

八、结论

基于以上所有信息,我们可以说在大多数情况下选择 HashMap 总是比 LinkedHashMap 更好。仅当我们有某些要求或用例需要维护添加到地图的元素的顺序时,我们才可以更喜欢 LinkedHashMap。

在大多数现实世界的用例中,两者都提供了几乎相同的性能。当我们拥有大量数据时,只有我们应该考虑它们之间的权衡。

快乐学习!!

参考:

LinkedHashMap Java 文档

地址:https://www.cundage.com/article/linkedhashmap.html

相关阅读

在 Java 中,Stream 接口有 &gtl;map() 和 flatMap() 方法,两者都是中间流操作并返回另一个流作为方法输出。 map() 与 flatMap() 之间的主要区别 是...
Java 8 Stream.map() 将 Stream&lt;X&gtl; 转换为 Stream&lt;Y&gtl;。对于每个 X 类型的对象,都会创建一个新的 Y 类型的对象,并将其放入新的...
Java Stream 收集教程展示了如何使用收集器进行缩减操作。 Java流 Java 流 是来自支持聚合操作的源的元素序列。流不存储元素;元素是按需计算的。从集合、数组或 I/O 资源等数据...
Java中的LinkedHashMap用于存储键值对,非常类似于HashMap类。不同之处在于 LinkedHashMap 维护插入其中的元素的顺序,而 HashMap 是无序的。 在这个 Ja...
Java forEach() 方法是一个实用函数,用于迭代集合,例如(List、Collect或Map)和 Stream。它用于对集合中的每个元素执行给定的操作。 forEach() 方法已添加...
Java HashMap 是 Collections 框架 的成员,用于存储键值对。每个键映射到单个值,并且不允许重复键。在本教程中,我们将了解HashMap 如何在内部存储键值对以及它如何防止...
Java HashMap 默认是不同步的。如果我们在多个线程正在添加和删除对的并发应用程序中从 HashMap 添加/删除键值对,我们最终可能会出现不一致的映射状态。学习同步 hashmap 和...
使用 Java 8 Stream API 以升序和降序(反向)顺序按值对 Map 进行排序 的简单快速使用示例。 逻辑的中心是方法 Map.Entry.comparingByValue(),它按...
学习用 Java 创建HashMap 的克隆。我们将看到用于创建 HashMap 的浅拷贝 和深拷贝 的 java 程序。 更多参考:Java 克隆指南 1. Clone HashMap——浅拷...
在上一篇文章中,我向您展示了如何在 Java 8 中通过键对 Map 进行排序,今天,我将教您使用 Java 如何通过值对 Map 进行排序 8 个特征,例如lambda 表达式、方法引用、流和...