对LinkedHashMap的理解

来源:互联网 发布:淘宝推广pid 编辑:程序博客网 时间:2024/04/29 18:18
  • 最初的认识:
    • 可以维护元素的插入顺序,按照插入顺序遍历;
    • 实现原理:LinkedHashmap的Entry除了该节点的hash值、key值、value值、next指向冲突时的后一个节点,还增加了指向前一个节点和后一个节点的指针:before、after,从而构成双向链表;除此之外,还有双向链表的头结点head和尾节点tail;
  • LinkedHashMap的具体实现:
    • 节点:
      static class Entry<K,V> extends HashMap.Node<K,V> {     Entry<K,V> before, after;     Entry(int hash, K key, V value, Node<K,V> next) {         super(hash, key, value, next);     } }
    • 头指针和尾指针:使用了transient关键字,该字段不进行序列化
      transient LinkedHashMap.Entry<K,V> head;
      transient LinkedHashMap.Entry<K,V> tail;
    • 元素的两种顺序:插入顺序、访问顺序(accessorder,可以用于实现LRU cache);
    • 插入顺序:遍历LinkedHashMap时,按照元素插入的顺序输出,put时,新元素追加在链表的尾部即可;
    • 访问顺序:创建LinkedHashMap时,传入参数accessorder指定为true,即表示按照访问顺序遍历数组;此刻,头部是最久未被访问的节点,尾部是最近刚访问过的节点;
      • get,如果该元素存在,则将节点从原位置删除,插入尾部;
      • put:如果新插入的元素key已存在,则替换其value,并将它从原位置删除,再插入尾部,如果不存在,则直接插入尾部;
    • 方法:removeEldestEntry
    • protected boolean removeEldestEntry(Map.Entry<K,V> eldest) {        return false;}
      重写该方法,可以指定在put元素时删除最久未被访问的,即双向链表头部的节点,从而实现LRU cache,默认不会删除。
  • LinkedHashmap的遍历
    • 使用EntrySet和迭代器;该例子中使用访问顺序,所以get操作会改变节点的顺序;
    • public static void main(String[] args)  {LinkedHashMap<String,Integer> map = new LinkedHashMap<String,Integer>(16,(float) 0.75,true);map.put("er", 1);map.put("rt", 2);map.put("ui", 3);map.put("op", 4);map.get("er");map.get("ui");Set<Entry<String, Integer>>  set = map.entrySet();Iterator<Entry<String, Integer>> itr = set.iterator();while(itr.hasNext()){Entry<String,Integer> ele = itr.next();System.out.println(ele.getKey()+" "+ele.getValue());}}
    • 如果使用下面这种方式遍历,就会抛异常;
    • public static void main(String[] args)  {LinkedHashMap<String,Integer> map = new LinkedHashMap<String,Integer>(16,(float) 0.75,true);map.put("er", 1);map.put("rt", 2);map.put("ui", 3);map.put("op", 4);Set<String> keyset = map.keySet();Iterator itr = keyset.iterator();while(itr.hasNext()){System.out.println(map.get(itr.next()));}}
      1Exception in thread "main" java.util.ConcurrentModificationExceptionat java.util.LinkedHashMap$LinkedHashIterator.nextNode(Unknown Source)at java.util.LinkedHashMap$LinkedKeyIterator.next(Unknown Source)at 验证例子.LinkedListTest.main(LinkedListTest.java:28)
      这是因为,new LinkedHashMap时,若指定accessorder为true,则get方法会调用afterNodeAccess方法,改变元素的位置,将其插入尾部,同时modCount++,所以调用Iterator 的next时,发现expectedModCount和modCount不一样,抛出ConcurrentModificationException;这是同步容器类的fail-fast机制;
  • 使用LinkedHashMap实现LRU cache
    • 关键是重写上面提到的removeEldestEntry方法
    • 参考链接:http://www.open-open.com/lib/view/open1410490776680.html


0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 儿子找对象不听父母怎么办 缺爱怎么办的搞笑回答 对象说有人追她怎么办 说了一句话媳妇非常生气怎么办 柔顺后头发太臭怎么办 积分兑换手机被骗了怎么办 老板对你的上级不满怎么办 如果老板不给工资怎么办 手机号码被标记为其他公司怎么办? 被标记为骚扰电话怎么办 手机被标记骚扰电话怎么办 360摄像头不支持5g怎么办 摄像头不支持5g网络怎么办 家里的wifi卡了怎么办 办信用卡没有座机号码怎么办 拨打电话时显示号码有误怎么办 个体营业执照怎么办企业支付宝 没满16岁怎么办电话卡 我的电话卡丢了怎么办 公司注销地税没有补齐怎么办 公司没有固定电话怎么办信用卡 申请信用卡公司没有固定电话怎么办 办理信用卡公司没有固定电话怎么办 江门市固话欠费停机后怎么办 物业交钥匙地面有裂缝怎么办 深圳交通卡丢了怎么办 没装etc走etc怎么办 找不到过敏源身体痒怎么办 微信客服电话打不通怎么办 华为手机网络信号不好怎么办 酷我好友动态加载不了怎么办? 米兔电话手表停机了怎么办 糖猫电话手表停机了怎么办 360电话手表停机了怎么办 小天才电话手表停机怎么办 移动手机卡不知道号码怎么办 天猫退款手机号换了怎么办 科目二考试脚抖怎么办 面试新工作没打电话怎么办 怀孕5个月胎位低怎么办 做业务很害怕打电话怎么办