数据结构

在HashMap的数据结构基础上,并通过双向链表维护顺序
image.png

  1. public class LinkedHashMap<K, V> extends HashMap<K, V> implements Map<K, V> {
  2. // 继承HashMap,并维护自己独有的双向链表
  3. transient LinkedHashMap.Entry<K, V> head;
  4. transient LinkedHashMap.Entry<K, V> tail;
  5. }

put()

调用的是HashMap的put()方法,但会使用LinkedHashMap覆盖的newNode()

  1. Node<K, V> newNode(int var1, K var2, V var3, Node<K, V> var4) {
  2. LinkedHashMap.Entry var5 = new LinkedHashMap.Entry(var1, var2, var3, var4);
  3. // 将插入的节点放到链表尾部
  4. this.linkNodeLast(var5);
  5. return var5;
  6. }
  7. private void linkNodeLast(LinkedHashMap.Entry<K, V> var1) {
  8. LinkedHashMap.Entry var2 = this.tail;
  9. this.tail = var1;
  10. if (var2 == null) {
  11. this.head = var1;
  12. } else {
  13. var1.before = var2;
  14. var2.after = var1;
  15. }
  16. }

get()

JDK1.8的LRU最近访问放在链表尾部

  1. public V get(Object var1) {
  2. Node var2;
  3. // 这里的getNode是HashMap get()的核心逻辑
  4. if ((var2 = this.getNode(hash(var1), var1)) == null) {
  5. return null;
  6. } else {
  7. // 添加了维护链表顺序的LRU逻辑
  8. if (this.accessOrder) {
  9. this.afterNodeAccess(var2);
  10. }
  11. return var2.value;
  12. }
  13. }
  14. void afterNodeAccess(Node<K, V> var1) {
  15. LinkedHashMap.Entry var2;
  16. if (this.accessOrder && (var2 = this.tail) != var1) {
  17. LinkedHashMap.Entry var3 = (LinkedHashMap.Entry)var1;
  18. LinkedHashMap.Entry var4 = var3.before;
  19. LinkedHashMap.Entry var5 = var3.after;
  20. var3.after = null;
  21. // 前置节点为Null,则原节点为head节点
  22. // 处理前后节点关系
  23. if (var4 == null) {
  24. this.head = var5;
  25. } else {
  26. var4.after = var5;
  27. }
  28. // 后置节点为null,则原节点为tail节点
  29. // 处理前后节点关系
  30. if (var5 != null) {
  31. var5.before = var4;
  32. } else {
  33. var2 = var4;
  34. }
  35. // 链表原来是否没元素
  36. if (var2 == null) {
  37. this.head = var3;
  38. } else {
  39. // 不是则将原节点放到链表尾部
  40. var3.before = var2;
  41. var2.after = var3;
  42. }
  43. this.tail = var3;
  44. ++this.modCount;
  45. }
  46. }