`

LinkedHashMap

    博客分类:
  • JDK
阅读更多
LinkedHashMap

这是一个继承自HashMap的类,在类说明中,这是一个非同步的,不能在多线程环境下使用,否则要自己实现同步.有两种模式,一种是元素访问的次数排序,一种是插入的时间排序
Linked内部含有一个private transient Entry header;来记录元素插入的顺序或者是元素被访问的顺序。
正如 LinkedHashMap的文档所说,LinkedHashMap简直就是为了实现LRU Cache(Least Recently Used)而编写的。正因为如此,在oscache或者是ehcache都使用到了LinkedHashMap。(oscache中是否使用LRU是可以配置的)
那么,这是如何实现的呢,见源码如下:
public V get(Object key) {
        Entry<K,V> e = (Entry<K,V>)getEntry(key);
        if (e == null)
            return null;
        e.recordAccess(this);
        return e.value;
}


这是取值的代码,请看得到实体的代码:
final Entry<K,V> getEntry(Object key) {
        int hash = (key == null) ? 0 : hash(key.hashCode());
        for (Entry<K,V> e = table[indexFor(hash, table.length)];
             e != null;
             e = e.next) {
            Object k;
            if (e.hash == hash &&
                ((k = e.key) == key || (key != null && key.equals(k))))
                return e;
        }
        return null;
 }


完全是从hashMap中得到实体对象,根据key.
这里调用了recordAccess方法,然后再返回value.请看:
void recordAccess(HashMap<K,V> m) {
            LinkedHashMap<K,V> lm = (LinkedHashMap<K,V>)m;
            if (lm.accessOrder) {
                lm.modCount++;
                remove();
                addBefore(lm.header);
            }
}


如果accessOrder实true,那是是访问排序,如果为false则为插入排序。
transient volatile int modCount;
这个参数可以用来标识修改次数,也可以用来标识访问次数

private void remove() {
            before.after = after;
            after.before = before;
}



从列表上移除该对象.
 private void addBefore(Entry<K,V> existingEntry) {
            after  = existingEntry;
            before = existingEntry.before;
            before.after = this;
            after.before = this;
}


把这个对象添加到第一个.
0
0
分享到:
评论
5 楼 a123159521 2011-04-26  
兄弟,你写了很多,其实linked hashMap和hashMap的存储是一致的,只是多了一个排序的过程,关于hashMap(可以查看我历史文章).排序就利于做缓存了,因为排在前面的优先级高,比如有10000个数据,我查找第一个就找到了,其实就循环了一次。
4 楼 zxy861114 2011-04-06  
下面来看看,取整个map元素的过程.
看之前,了解一下LinkedHashMap的构造过程。
private LinkedHash\Iterator()
{
     this$0 = LinkedHashMap.this;
     super();
     nextEntry = header.after;
     lastReturned = null;
     expectedModCount = modCount;
}
请注意nextEntry的初始化过程.
取的过程肯定是由迭代器完成。由于KeyIterator与EntrySet的next方法都与EntryIterator的next方法类似,以EntryIterator说明。
public Map.Entry next()
{
    return nextEntry();
}

LinkedHashMap.Entry nextEntry()
{
     if(modCount != expectedModCount)
         throw new ConcurrentModificationException();
     if(nextEntry == header)
     {
         throw new NoSuchElementException();
     } else
     {
         LinkedHashMap.Entry entry = lastReturned = nextEntry;
         nextEntry = entry.after;
         return entry;
     }
}
从nextEntry我们可以看出,它是将heaeder的后续元素一个个取出来的过程。
至于accessOrder,当为true时。对于方法
void recordAccess(HashMap hashmap)
{
    LinkedHashMap linkedhashmap = (LinkedHashMap)hashmap;
    if(linkedhashmap.accessOrder)
    {
        linkedhashmap.modCount++;
        remove();
        addBefore(linkedhashmap.header);
    }
}
它会将访问到的元素,删除掉,然后到加header的前面。由前面分析就可知,排序就会将访问过程计算在内。
3 楼 zxy861114 2011-04-06  
它主要是一般的HashMap存放数据的过程。不过请注意addEntry方法。
void addEntry(int i, Object obj, Object obj1, int j)
{
    createEntry(i, obj, obj1, j);
    Entry entry = header.after;
    if(removeEldestEntry(entry))
        removeEntryForKey(entry.key);
    else
    if(size >= threshold)
        resize(2 * table.length);
}
createEntry方法会调用entry1.addBefore(header)方法,它会在header前面插入一个元素.这是我要谈的重点.
void createEntry(int i, Object obj, Object obj1, int j)
{
    HashMap.Entry entry = table[j];
    Entry entry1 = new Entry(i, obj, obj1, entry);
    table[j] = entry1;
    entry1.addBefore(header);
    size++;
}
此处为addBeofre的指针处理过程。
private void addBefore(Entry entry)
{
     after = entry;
     before = entry.before;
     before.after = this;
     after.before = this;
}

我以图解来看看这段代码贴不上来,晕。(就是addBefore,从只有header到有两个Entry的过程,addBefore时,after指针指向的是按插入顺序的)
2 楼 zxy861114 2011-04-06  
"如果accessOrder实true,那是是访问排序,如果为false则为插入排序。 "
你的这里的访问排序,包括插入。差点说你错啦,哈哈!

我来接着你的讲讲,排序的过程.

首先实例化LinkedHashMap时,会首先初始化父类HashMap
public HashMap()
  {
      entrySet = null;
      loadFactor = 0.75F;
      threshold = 12;
      table = new Entry[16];
      init();
  }
它会调用LinkedHashMap中的init方法对header进行初始化.
void init()
{
     header = new Entry(-1, null, null, null);
     header.before = header.after = header;
}

接着,再来看看元素放进去的过程.这个put方法为父类hashMap的方法。
public Object put(Object obj, Object obj1)
{
    if(obj == null)
        return putForNullKey(obj1);
    int i = hash(obj.hashCode());
    int j = indexFor(i, table.length);
    for(Entry entry = table[j]; entry != null; entry = entry.next)
    {
        Object obj2;
        if(entry.hash == i && ((obj2 = entry.key) == obj || obj.equals(obj2)))
        {
            Object obj3 = entry.value;
            entry.value = obj1;
            entry.recordAccess(this);
            return obj3;
        }
    }

    modCount++;
    addEntry(i, obj, obj1, j);
    return null;
}
1 楼 zxy861114 2011-04-06  
晕,我写了这么多竟然评论,我公司代理过滤。汗!

相关推荐

    java中HashMap,LinkedHashMap,TreeMap,HashTable的区别

    ### Java中HashMap, LinkedHashMap, TreeMap,HashTable的区别 在Java编程语言中,`Map`接口是集合框架中的一个重要组成部分,用于存储键值对。本文将详细分析四种常用的`Map`实现类:`HashMap`, `LinkedHashMap`, ...

    HashMap,HashTable,LinkedHashMap,TreeMap的区别

    HashMap, HashTable, LinkedHashMap, TreeMap 的区别 在 Java 中,Map 是一个非常重要的集合类,用于存储键值对。其中,HashMap, HashTable, LinkedHashMap, TreeMap 是四种常用的 Map 实现类,每种类都有其特点和...

    LinkedHashmap的使用

    **HashMap与LinkedHashMap的区别** HashMap是Java集合框架中的一员,它是基于哈希表实现的,提供了快速的插入、删除和查找操作,平均时间复杂度为O(1)。然而,HashMap不保证元素的顺序,迭代时元素的顺序可能与插入...

    一文搞懂Java的LinkedHashMap.docx

    《深入解析Java的LinkedHashMap》 HashMap作为Java中常用的键值对存储结构,以其高效的查找速度赢得了广大开发者们的青睐。然而,HashMap的无序性在某些特定场景下却显得力不从心,例如当我们需要按照插入顺序来...

    JavaLinkedHashMap源码解析Java开发Ja

    Java LinkedHashMap 是一个根据插入顺序或者访问顺序来维护元素顺序的哈希表与链表相结合的数据结构。在 Java 集合框架中,它继承自 HashMap 类,并实现了 Map 接口。LinkedHashMap 的特点在于,它不仅仅是一个哈希...

    Java集合系列(LinkedHashMap+LinkedList+ArrayList)

    Java 集合系列(LinkedHashMap+LinkedList+ArrayList) Java 集合系列是 Java 语言中的一种数据结构,用于存储和操作数据。今天,我们将介绍 Java 集合系列中的三个重要成员:LinkedHashMap、LinkedList 和 ArrayList...

    java软件技术文档-深入java8的集合4:LinkedHashMap的实现原理.pdf

    K,V&gt; p) { } 这些方法是 HashMap 为 LinkedHashMap 提供的回调接口,用于在插入、访问和删除节点后执行特定的操作。LinkedHashMap 利用这些回调方法来维护其内部链表的顺序。 1. **afterNodeAccess(Node,V&gt; p)**: ...

    java HashMap,TreeMap与LinkedHashMap的详解

    在Java编程语言中,`HashMap`、`TreeMap`和`LinkedHashMap`都是`java.util.Map`接口的实现,它们提供了不同的数据存储和访问策略。本文将深入探讨这三种数据结构的特点、工作原理以及适用场景。 1. **HashMap** `...

    java集合-LinkedHashMap的使用

    LinkedHashMap是Java中的一种特殊类型的HashMap,它保留了插入顺序,即按照元素插入的先后顺序进行排序

    Java集合框架源码分析之LinkedHashMap详解

    Java集合框架源码分析之LinkedHashMap详解 Java集合框架中的LinkedHashMap是HashMap的子类,它继承了HashMap的存储结构,但引入了一个双向链表的头结点,将所有put到LinkedHashMap的节点连接成一个双向循环链表,...

    Java集合系列之LinkedHashMap源码分析

    Java集合系列之LinkedHashMap源码分析 Java集合系列之LinkedHashMap源码分析是Java集合框架中的一部分,主要对LinkedHashMap的源码进行了详细的分析。LinkedHashMap是继承自HashMap的,它重新写了一个Entry,在原来...

    Java使用LinkedHashMap进行分数排序

    Java使用LinkedHashMap进行分数排序 Java中进行分数排序是非常重要的,特别是在学生成绩统计的问题中。传统的排序方法对于排序存在许多相同元素的情况有些浪费,明显即使值相等,两个元素之间也要比较一下,这在...

    set:使用LinkedHashMap在Go(Golang)中简单的Set数据结构实现

    Set是使用LinkedHashMap在Go(Golang)中简单的Set数据结构实现。 该库允许您获取一组int64或string而没有重复的项目。 用法 package main import ( "fmt" "github.com/StudioSol/set" ) func main () { ...

    Java LinkedHashMap工作原理及实现

     在理解了#7 介绍的HashMap后,我们来学习LinkedHashMap的工作原理及实现。首先还是类似的,我们写一个简单的LinkedHashMap的程序:  LinkedHashMap&lt;String&gt; lmap = new LinkedHashMap();  lmap.put(语文, 1)...

    HashMap遍历

    ### HashMap遍历详解 在Java编程中,`HashMap`是一种常用的数据结构,它实现了`Map`接口,提供了基于哈希表的存储方式,...同时,对于不允许null值的情况,可以选择`LinkedHashMap`或`TreeMap`等其他类型的地图实现。

Global site tag (gtag.js) - Google Analytics