linkedHashMap跟和HashMap结构,只是加了两个属性,也就是为了记录前一个插入的元素(before)和记录后一个插入的元素(next)。
LinkedHashMap定义的Entry结构如下:
next和after可能会指向同一个Entry,next也可能指向null。
整个结构如下:(图片来http://www.cnblogs.com/chenpi/p/5294077.html)
从上图,我们可以看到,LinkedHashMap跟HashMap插入元素的原理相同,通过hash值寻找插入到数组的位置,只是每次插入的元素需要维护其前一个节点(before)和后一个节点(after)的指针。
LinkedHashMap实现:
package com.java.myutil;
/**
* 继承我们已经实现的HashMap方法
*/
public class LinkedHashMap extends HashMap implements Map {
//双向循环链表的头节点
private Entry head;
int size=0;
//初始化时,循环链表的前一个和后一个节点都是自身
public LinkedHashMap() {
head=new Entry(-1, null, null, null);
head.before=head.after=head;
}
static class Entry extends HashMap.Node{
Entry before;//指向前一个Entry,
Entry after;//指向后一个Entry,
Entry(int hash, Object key, Object value, Node next) {
super(hash, key, value, next);
}
//往双向循环链表里天添加节点,都是在头结点前加入
public void addBefore(Entry head) {
this.after=head;
this.before=head.before;
this.after.before=this;
this.before.after=this;
}
}
public int size() {
return size;
}
public boolean isEmpty() {
return size==0;
}
public Object get(Object key) {
int hash = (key == null) ? 0 : hash(key);
int i= indexFor(hash, table.length);
for (Node e = table[i];e != null;e = e.next) {
Object k;
if (e.hash == hash &&
((k = e.key) == key || (key != null && key.equals(k))))
return e.getValue();
}
return null;
}
/**
* LinkedHashMap继承自HashMap,put(),方法,使用继承的HashMap的put方法,但是重写了put方法中的addEntry方法
*/
@Override
public void addEntry(Object key, Object value, int hashValue, int i) {
//在这里也可以通过size的大小决定是否扩展数组大小
/*
* 省略...可看hashmap的扩展
**/
//在继承的HashMap的put方法中,到这一步,已经判断如下:如果i位置没有数据,或者i位置有数据,但是key是新的key,则新增节点
HashMap.Node old=table[i];
Entry entry=new Entry(hashValue, key, value, old);
table[i]=entry;
//将新增的entry放到双向循环列表的头部
entry.addBefore(head);
size++;
}
public static void main(String[] args) {
LinkedHashMap linkedHashMap =new LinkedHashMap();
linkedHashMap.put("aaa", "111");
linkedHashMap.put("bbb", "222");
linkedHashMap.put("ccc", "333");
System.out.println(linkedHashMap.get("aaa"));
}
}