LinkedHashMap如何保证顺序性

一. 前言

先看一个例子,我们想在页面展示一周内的消费变化情况,用echarts面积图进行展示。如下:
在这里插入图片描述
我们在后台将数据构造完成

HashMap<String, Integer> map = new HashMap<>();
map.put("星期一", 40);
map.put("星期二", 43);
map.put("星期三", 35);
map.put("星期四", 55);
map.put("星期五", 45);
map.put("星期六", 35);
map.put("星期日", 30);

然而页面上一展示,发现并非如此,我们打印出来看,发现顺序并非我们所想,先put进去的先get出来

for (Map.Entry<String, Integer> entry : map.entrySet()){
   
    System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());
}
/**
 * 结果如下:
 * key: 星期二, value: 40
 * key: 星期六, value: 35
 * key: 星期三, value: 50
 * key: 星期四, value: 55
 * key: 星期五, value: 45
 * key: 星期日, value: 65
 * key: 星期一, value: 30
 */

那么如何保证预期展示结果如我们所想呢,这个时候就需要用到LinkedHashMap实体。

二. 初识LinkedHashMap

首先我们把上述代码用LinkedHashMap进行重构

LinkedHashMap<String, Integer> map = new LinkedHashMap<>();
map.put("星期一", 40);
map.put("星期二", 43);
map.put("星期三", 35);
map.put("星期四", 55);
map.put("星期五", 45);
map.put("星期六", 35);
map.put("星期日", 30);
for (Map.Entry<String, Integer> entry : map.entrySet()){
   
    System.out.println("key: " + entry.getKey() + ", value: " + entry.getValue());
}

这个时候,结果正如我们所预期

key: 星期一, value: 40
key: 星期二, value: 43
key: 星期三, value: 35
key: 星期四, value: 55
key: 星期五, value: 45
key: 星期六, value: 35
key: 星期日, value: 30

LinkedHashMap继承了HashMap类,是HashMap的子类,LinkedHashMap的大多数方法的实现直接使用了父类HashMap的方法,关于HashMap在前面的章节已经讲过了,《HashMap原理(一) 概念和底层架构》《HashMap原理(二) 扩容机制及存取原理》

LinkedHashMap可以说是HashMap和LinkedList的集合体,既使用了HashMap的数据结构,又借用了LinkedList双向链表的结构(关于LinkedList可参考Java集合 LinkedList的原理及使用),那么这样的结构如何实现的呢,我们看一下LinkedHashMap的类结构
在这里插入图片描述
我们看到LinkedHashMap中定义了一个Entry静态内部类,定义了5个构造器,一些成员变量,如head,tail,accessOrder,并继承了HashMap的方法,同时实现了一些迭代器方法。我们先看一下Entry类

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);
    }
}

我们看到这个静态内部类很简单,继承了HashMap的Node内部类,我们知道Node类是HashMap的底层数据结构,实现了数组+链表/红黑树的结构,而Entry类保留了HashMap的数据结构,同时通过before,after实现了双向链表结构(HashMap中Node类只有next属性,并不具备双向链表结构)。那么before,after和next到底什么关系呢。
在这里插入图片描述
看上面的结构图,定义了头结点head,当我们调用迭代器进行遍历时,通过head开始遍历,通过before属性可以不断找到下一个,直到tail尾结点,从而实现顺序性。而在同一个hash(在上图中表现了同一行)链表内部after和next效果是一样的。不同点在于before和after可以连接不同hash之间的链表。

前面我们发现数据结构已经完全支持其顺序性了,接下来我们再看一下构造方法,看一下比起HashMap的构造方法是否有不同。

// 构造方法1,构造一个指定初始容量和负载因子的、按照插入顺序的LinkedList
public LinkedHashMap(int initialCapacity, float loadFactor) {
   
    super(initialCapacity, loadFactor);
    accessOrder = false;
}
// 构造方法2,构造一个指定初始容量的LinkedHashMap,取得键值对的顺序是插入顺序
public LinkedHashMap(int initialCapacity) {
   
    super(initialCapacity
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值