Java集合-LinkHashMap

HashMap实现了一个Hash表为主的数据结构,他将数据根据key的哈希值,存储于一个数组中,通过合理的碰撞,将相同hash值的数据通过链式结构存储。

很显然,这种hash结构存储的数据是无序的,JDK通过继承HashMap实现了集中有序的HashMap数据结构,如链表式的LinkHashMap

首先看,LinkHashMap是继承与HashMap的:

public class LinkedHashMap extends HashMap implements Map

那么这个Link是怎么实现顺序存储的呢?

他通过构造出另一个数据结构Doubly Linked List存储数据顺序,注意,这里他即实现了HashMap原有的数据结构进行数据存储,再实现了另一个Doubly Linked List去存储数据的顺序,这两个数据结构是相互独立,同时存在的。

private transient Entry header;

这里的header就是该link的头元素,其中Entry在这里重新进行了定义:

 private static class Entry extends HashMap.Entry {
    
    Entry before, after;
    Entry(int hash, K key, V value, HashMap.Entry next) {
            super(hash, key, value, next);
        }
}

他既继承了原有的Entry结构,同时,加入了before, after的双向指针。

那么看一下,header在LinkHashMap初始化时:

void init() {
    header = new Entry<>(-1, null, null, null);
    header.before = header.after = header;
}

header定义了一个空的entry,同时这个entry的hash值为-1(也就是这个entry不会存入HashMap中的hash table中)。同时将entry的双向指针都指向自己。


Java集合-LinkHashMap_第1张图片
image

那么,现在看一下,怎么向这个header链表新增一个元素。LinkHashMap继承了put方法,同时重写了createEntry方法:

void createEntry(int hash, K key, V value, int bucketIndex) {
    HashMap.Entry old = table[bucketIndex];
    Entry e = new Entry<>(hash, key, value, old);
    table[bucketIndex] = e;
    e.addBefore(header);
    size++;
}

其中,加入了e.addBefore(header),这里的addBefore放在在Entry中定义为:

private void addBefore(Entry existingEntry) {
    after  = existingEntry;
    before = existingEntry.before;
    before.after = this;
    after.before = this;
}

举例,在header中加入第一个entryA时:


Java集合-LinkHashMap_第2张图片
image

那么EntryA加在了Header之前,那么插入第二个元素EntryB时:


Java集合-LinkHashMap_第3张图片
image

那么这里就是在entryA和header之间加入一个元素。

上面介绍了如何将一个entry加入到header中,使用的是put方法,同时linkHashMap还提供了在get的方法中修改header顺序的方法,这里就不讲述了。

总结:
==LinkHashMap实际是在HashMap的基础上再实现了一个链表的结构进行存储数据顺序的。==

你可能感兴趣的:(Java集合-LinkHashMap)