今天有个需求,要求把某个公司和这个公司的有序产品放到map中存储,同时放入这个map中的公司时有顺序要求的——什么顺序放进去,什么顺序拿出来!
用普通的HashMap解决这个需求就不合适了。jdk提供的集合框架中的LinkedHashMap比较适合这个需求。那么他又是怎么实现这个功能的呢?一起来看看源码吧。
public class LinkedHashMap<K,V>
extends HashMap<K,V>
implements Map<K,V>
这里可以看出,LinkedHashMap就是HashMap的一个子类。
static class Entry<K,V> implements Map.Entry<K,V> {
final K key;
V value;
final int hash;
Entry<K,V> next;
private static class Entry<K,V> extends HashMap.Entry<K,V> {
// 可以看到在HashMap.Entry基础上,增加了下面两个属性!
// These fields comprise the doubly linked list used for iteration.
Entry<K,V> before, after;
public V put(K key, V value) {
//从这里可以看出,HashMap是允许以null为key的存储的!
if (key == null)
return putForNullKey(value);
int hash = hash(key.hashCode());
int i = indexFor(hash, table.length);
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
modCount++;
//LinkedHashMap override了下面这个方法!
addEntry(hash, key, value, i);
return null;
}
- 那么put时,两个方法最大的区别就是上面的这个addEntry方法了,分别看一下:
//HashMap中的方法
void addEntry(int hash, K key, V value, int bucketIndex) {
Entry<K,V> e = table[bucketIndex];
//这里可以看出,如果hash不均匀的话,会造成table中的某些entry元素比较庞大(因为里面会嵌套N层的子entry)
table[bucketIndex] = new Entry<K,V>(hash, key, value, e);
if (size++ >= threshold)
resize(2 * table.length);
}
//LinkedHashMap中的方法
void addEntry(int hash, K key, V value, int bucketIndex) {
createEntry(hash, key, value, bucketIndex);
// Remove eldest entry if instructed, else grow capacity if appropriate
Entry<K,V> eldest = header.after;
//这里LinkedHashMap本身的removeEldestEntry方法是直接返回false的,但他的N个子类可能会采用不用的淘汰老元素的策略。
if (removeEldestEntry(eldest)) {
removeEntryForKey(eldest.key);
} else {
if (size >= threshold)
resize(2 * table.length);
}
}
void createEntry(int hash, K key, V value, int bucketIndex) {
HashMap.Entry<K,V> old = table[bucketIndex];
Entry<K,V> e = new Entry<K,V>(hash, key, value, old);
table[bucketIndex] = e;
//注意:这里将新创建的元素插入到连表里header的前面(也就是Map的put方法中将entry加入双向链表的地方)
e.addBefore(header);
size++;
}
- 剩下就是看LinkedHashMap是如何实现这个按插入的顺序展示entrySet中的元素了:
//HashMap中的EntryIterator中的nextEntry方法
Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
Entry<K,V> e = next;
if (e == null)
throw new NoSuchElementException();
Entry<K,V> n = e.next;
Entry[] t = table;
int i = index;
while (n == null && i > 0)
n = t[--i];
index = i;
next = n;
return current = e;
}
//LinkedHashMap重新定义了自己的内部类EntryIterator(当然其实HashMap中的EntryIterator也是private的),这里关键的不同就在这个nextEntry方法了
Entry<K,V> nextEntry() {
if (modCount != expectedModCount)
throw new ConcurrentModificationException();
if (nextEntry == header)
throw new NoSuchElementException();
Entry<K,V> e = lastReturned = nextEntry;
//关键在这里,会将nextEntry指向当前元素的下一个元素!
nextEntry = e.after;
return e;
}
好了,关键原理找到了,其实其中还有很多细节,不过对理解原理不重要,可以暂时忽略!
分享到:
相关推荐
java中HashMap,LinkedHashMap,TreeMap,HashTable的区别
这是关于Java学习的主要针对LinkedHashMap的实现原理
深入Java集合学习系列(四): LinkedHashMap的实现原理
HashMap,HashTable,LinkedHashMap,TreeMap的区别
这个demo主要讲解了LinkedHashmap的使用,希望可以帮助需要的同学.
LinkedHashMap是Java中的一种特殊类型的HashMap,它保留了插入顺序,即按照元素插入的先后顺序进行排序
本教程特点: 1.更适合零基础学员: ·自Java语言起源始,循序渐进,知识点剖析细致且每章配备大量随堂练习,让你步步为营,学得透彻、练得明白 ·拒绝晦涩难懂的呆板教学,宋老师语言生动幽默,举例形象生动深入浅...
JavaLinkedHashMap源码解析Java开发Java经验技巧共7页.pdf.zip
今天说一下LinkedHashMap的主要点,因为有同学不太清楚它和HashMap的区别。今天大概总结一下,也是方便自己进行学习。 写在前面 LinkedHashMap的内部维护了一个双向链表。可以按照元素的插入顺序进行访问,也可以...
Java集合系列(LinkedHashMap+LinkedList+ArrayList)
Set是使用LinkedHashMap在Go(Golang)中简单的Set数据结构实现。 该库允许您获取一组int64或string而没有重复的项目。 用法 package main import ( "fmt" "github.com/StudioSol/set" ) func main () { ...
在理解了#7 介绍的HashMap后,我们来学习LinkedHashMap的工作原理及实现。首先还是类似的,我们写一个简单的LinkedHashMap的程序: LinkedHashMap<String> lmap = new LinkedHashMap(); lmap.put(语文, 1)...
主要介绍了 java HashMap,TreeMap与LinkedHashMap的详解的相关资料,这里提供实例代码,帮助大家学习理解 这部分的内容,需要的朋友可以参考下
RiteLinked——类似HashMap的容器,以用户可控的顺序保存它们的键值对RiteLinked提供了LinkedHashMap和LinkedHashSet更多最新版本。您可以在std或no_std环境中轻松使用它。一些实用的功能组合,支持,帮助您更好地将...
将LinkedHashMap转换为json,反之亦然 如何使用 LinkedHashMap requestData = new LinkedHashMap(); LinkedHashMap auth =新的LinkedHashMap(); auth.put(“ ServiceName”,“ Login”); auth.put(“ ...
主要介绍了Java集合框架源码分析之LinkedHashMap详解,内容包括了linkedhashmap的简介和源码剖析以及关于LinkedHashMap的源码总结,内容丰富,需要的朋友可以参考下。
主要介绍了Java使用LinkedHashMap进行分数排序的相关代码,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
主要为大家详细介绍了Java集合系列之LinkedHashMap源码分析,具有一定的参考价值,感兴趣的小伙伴们可以参考一下