Java集合框架2LinkedSHashMap

2017-04-06  本文已影响0人  paulpaullong

LinkedHashMap的定义

package java.util;
import java.io.*;
public class LinkedHashMap<K,V> extends HashMap<K,V> implements Map<K,V> {
}

LinkedHashMap的数据结构

Map<String,Integer> map = new LinkedHashMap<>();
        map.put("s1", 1);
        map.put("s2", 2);
        map.put("s3", 3);
        map.put("s4", 4);
        map.put("s5", 5);
        map.put(null, 9);
        map.put("s6", 6);
        map.put("s7", 7);
        map.put("s8", 8);
        map.put(null, 11);
        for(Map.Entry<String,Integer> entry:map.entrySet())
        {
            System.out.println(entry.getKey()+":"+entry.getValue());
        }
        System.out.println(map);
s1:1
s2:2
s3:3
s4:4
s5:5
null:11
s6:6
s7:7
s8:8
{s1=1, s2=2, s3=3, s4=4, s5=5, null=11, s6=6, s7=7, s8=8}

LinkedHashMap的其他特性

public LinkedHashMap(int initialCapacity, float loadFactor, boolean accessOrder) {
        super(initialCapacity, loadFactor);
        this.accessOrder = accessOrder;
}
       Map<String,Integer> map = new LinkedHashMap<>(16,0.75f,true);
        map.put("s1", 1);
        map.put("s2", 2);
        map.put("s3", 3);
        map.put("s4", 4);
        map.put("s5", 5);
        map.put(null, 9);
        map.put("s6", 6);
        map.put("s7", 7);
        map.put("s8", 8);
        map.put(null, 11); // 此处null的key值set了第二次,也能改变数据存储的结果
        map.get("s6"); // 此处是get调用,也能改变数据存储的结果
        for(Map.Entry<String,Integer> entry:map.entrySet())
        {
            System.out.println(entry.getKey()+":"+entry.getValue());
        }

2)运行结果

s1:1
s2:2
s3:3
s4:4
s5:5
s7:7
s8:8
null:11
s6:6

3)原因分析
LinkedHashMap工作在按照元素访问顺序排序的模式中,get()方法会修改LinkedHashMap中的链表结构,以便将最近访问的元素放置到链表的末尾。

for(Iterator<String> iterator = map.keySet().iterator();iterator.hasNext();) {
    String name = iterator.next();
    System.out.println(name+"->"+map.get(name));
}

运行结果:

s1->1
Exception in thread "main" java.util.ConcurrentModificationException
    at java.util.LinkedHashMap$LinkedHashIterator.nextEntry(Unknown Source)
    at java.util.LinkedHashMap$KeyIterator.next(Unknown Source)
    at collections.map.LinkedHashMapTest.main(LinkedHashMapTest.java:33)

3)原因分析
ConcurrentModificationException异常一般会在集合迭代过程中被修改事抛出。不仅仅是LinkedHashMap,所有的集合都不允许在迭代器模式中修改集合的结构。一般认为,put()、remove()方法会修改集合的结构,因此不能在迭代器中使用。
但该模式下的get()方法同样会改变它的存储顺序,导致抛异常。

LinkedHashMap的典型应用

import java.util.ArrayList;
import java.util.Collection;
import java.util.LinkedHashMap;
import java.util.Map;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
public class LRULinkedHashMap<K, V> extends LinkedHashMap<K, V> {

    private static final long serialVersionUID = 7428629360694235373L;

    private final int maxCapacity;

    private static final float DEFAULT_LOAD_FACTOR = 0.75f;

    private final Lock lock = new ReentrantLock();

    public LRULinkedHashMap(int maxCapacity) {
        super(maxCapacity, DEFAULT_LOAD_FACTOR, true);
        this.maxCapacity = maxCapacity;
    }

    @Override
    protected boolean removeEldestEntry(java.util.Map.Entry<K, V> eldest) {
        return size() > maxCapacity;
    }

    @Override
    public boolean containsKey(Object key) {
        try {
            lock.lock();
            return super.containsKey(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V get(Object key) {
        try {
            lock.lock();
            return super.get(key);
        } finally {
            lock.unlock();
        }
    }

    @Override
    public V put(K key, V value) {
        try {
            lock.lock();
            return super.put(key, value);
        } finally {
            lock.unlock();
        }
    }

    public int size() {
        try {
            lock.lock();
            return super.size();
        } finally {
            lock.unlock();
        }
    }

    public void clear() {
        try {
            lock.lock();
            super.clear();
        } finally {
            lock.unlock();
        }
    }

    public Collection<Map.Entry<K, V>> getAll() {
        try {
            lock.lock();
            return new ArrayList<Map.Entry<K, V>>(super.entrySet());
        } finally {
            lock.unlock();
        }
    }

    public static void main(String[] args) {
        LRULinkedHashMap<String, String> lruMap = new LRULinkedHashMap<>(4);
        lruMap.put("first", "1");
        lruMap.put("second", "2");
        lruMap.put("third", "3");
        lruMap.put("fourth", "4");
                lruMap.put("fivth", "5");
        lruMap.get("fivth");
        lruMap.get("fourth");
        lruMap.get("third");        
                lruMap.get("second");

        for (Map.Entry<String, String> entry : lruMap.entrySet()) {
            System.out.println(entry.getKey() + ":" + entry.getValue());
        }
    }
}
first:1
fourth:4
second:two
fivth:5
上一篇 下一篇

猜你喜欢

热点阅读