zoukankan      html  css  js  c++  java
  • 对 HashMap 的一次扩展

    一、需求

    (1) 容量200 Capacity = 200.                       ——> 静态数据,可提供设置.
    (2) 最近操作(get/put)的元数,总放在最前.          ——> 元素频繁位移,从效率考虑,用链表实现.
    (3) 超过 Capacity 值后,移除最后一个元素,即第200号元素.   ——> 结合下一条,满载后,可能频繁操作末端元素,考虑用双向链表.

    二、数据结构设计

     1     @RequiredArgsConstructor
     2     class ButterHashMap<K,V> extends LinkedHashMap<K,V>{
     3         @NonNull
     4         @Getter@Setter
     5         int capacity;           // 容量值
     6         @Getter@Setter
     7         int limit;              // 当前已用量
     8         DoubleLinkedNode table;
     9 
    10         @RequiredArgsConstructor
    11         class DoubleLinkedNode<K,V> extends LinkedHashMap {
    12             @NonNull
    13             @Getter
    14             @Setter
    15             K k;
    16             @NonNull
    17             @Getter
    18             @Setter
    19             V v;
    20             DoubleLinkedNode head;
    21             DoubleLinkedNode pre;
    22             @Getter@Setter
    23             DoubleLinkedNode next;
    24             DoubleLinkedNode tail;
    25         }
    26 
    27     }
    数据结构

    三、功能实现

      1     @RequiredArgsConstructor
      2     class ButterHashMap<K,V> extends LinkedHashMap<K,V>{
      3         @Override
      4         public V put(K key,V value){
      5             if(checkCapacity()){
      6                 // 容量未满:添加首节点
      7                 this.createNode(key, value, false);
      8             }else{
      9                 // 容量已满:添加首节点,移除尾节点
     10                 this.createNode(key, value, true);
     11             }
     12             System.out.println("添加后——limit : "+ limit + ", capacity : "+ capacity);
     13             return value;
     14         }
     15 
     16         private boolean checkCapacity(){
     17             int flag = limit+1;
     18             if(flag > capacity) return false;
     19             return true;
     20         }
     21 
     22         // 不能判断 是否存在 K-V,因为 V 可能正好为 null;
     23         public V getValue(K key){
     24             DoubleLinkedNode<K,V> e = getNode(key);
     25             if(e != null) return e.v;
     26             return null;
     27         }
     28         
     29         private DoubleLinkedNode createNode(K key,V value,boolean isFlow){
     30             // 先查询一下
     31             DoubleLinkedNode src = this.getNode(key);
     32             if(src != null){
     33                 // 有值,替换 value 即可
     34                 src.setV(value);
     35                 return src;
     36             }
     37 
     38             DoubleLinkedNode newNode = new DoubleLinkedNode(key, value);
     39             if(!isFlow && limit == 0){
     40                 this.table = newNode.head = newNode.tail = newNode;
     41                 limit++;
     42                 return this.table;
     43             }
     44 
     45             this.table.pre = newNode;
     46             newNode.next = this.table;
     47             newNode.tail = this.table.tail;
     48             this.table = newNode;
     49             this.table.head = newNode;
     50             if(isFlow){
     51                 // 容量已满:尾节点,向前移一个节点,节点总数不变
     52                 this.table.tail = this.table.tail.pre;
     53                 // 相当于移除原来的尾节点
     54                 this.table.tail.next = null;
     55             }else{
     56                 limit++;
     57             }
     58             return this.table;
     59         }
     60 
     61         // 提供 public 的原因在于,本方法 能判断 是否存在 K-V. 若存在,返回值不为 null.
     62         public DoubleLinkedNode<K,V> getNode(K key){
     63             if (this.table == null) return null;
     64 
     65             DoubleLinkedNode<K,V> t = this.table,c = this.table,
     66                     stop =  this.table.head,h = this.table.head;
     67             // t:table, c:change, h:head
     68             while (c.getK() != key){
     69                 c = c.next;
     70                 if(c == null || stop == c){
     71                     // 未找到节点
     72                     return null;
     73                 }
     74             }
     75 
     76             // A : getA
     77             // tail、head 无需调整
     78             if(h.next == null){
     79                 return h;
     80             }
     81 
     82             // A ——> B : getA : B ——> A
     83             // tail 有影响,需要调整;head 需要调整
     84             if(c.next == null){
     85                 c.pre.next = null;
     86                 c.pre.tail = c.pre;
     87                 c.tail = c.pre;
     88 
     89                 c.next = t.head;
     90                 t.head = c;
     91                 t.pre = c;
     92                 c.next = t;
     93                 t.tail = c.pre;
     94 
     95                 c.head = c;
     96                 c.tail = c.pre;
     97                 c.pre = null;
     98                 this.table = c;
     99                 this.table.head = c;
    100                 this.table.next = h;
    101                 this.table.tail = c.tail;
    102                 return c;
    103             }
    104 
    105             // A ——> B ——> C:getB:A ——> C ——> B
    106             // tail 无影响,无需调整;head 需要调整
    107             c.next.pre = c.pre;
    108             c.pre.next = c.next;
    109             c.next.head = c;
    110             c.pre.head = c;
    111 
    112             h.head = c;
    113             h.pre = c;
    114             c.next = t;
    115             c.head = c;
    116 
    117             c.pre = null;
    118             this.table = c;
    119             this.table.head = c;
    120             this.table.next = h;
    121             return c;
    122         }
    123     }
    完善 ButterHashMap<K,V> 功能,省略了上面数据结构的代码(他们是一起的)

    四、测试检验

     1 package test;
     2 
     3 import lombok.*;
     4 
     5 import java.util.*;
     6 
     7 
     8 public class ButterHashMapTest {
     9 
    10 public static void main(String[] args) {
    11 
    12     ButterHashMapTest bt = new ButterHashMapTest();
    13     bt.testButterHashMap();
    14 }
    15 
    16     void testButterHashMap(){
    17         ButterHashMap betterHashMap = new ButterHashMap(5);
    18         betterHashMap.put("a",1);
    19         betterHashMap.put("b",2);
    20         betterHashMap.put("c",3);
    21         betterHashMap.put("d",4);
    22         this.printMap("put(d-4)", betterHashMap);
    23         betterHashMap.put("e",5);
    24         this.printMap("put(e-5)", betterHashMap);
    25         betterHashMap.put("c",33);
    26         System.out.println("========添加相同的 ‘c’:33 《《 ============");
    27         this.printMap("put(e-5)", betterHashMap);
    28         System.out.println("========添加相同的 ‘c’:33  》》============");
    29         betterHashMap.put("f",6);
    30         this.printMap("put(f-6)", betterHashMap);
    31         betterHashMap.getValue("e");
    32         this.printMap("getE", betterHashMap);
    33     }
    34 
    35     public void printMap(String context, ButterHashMap betterHashMap){
    36         System.out.println("打印" +context+ "开始《《《===============");
    37         if(betterHashMap != null){
    38             ButterHashMap.DoubleLinkedNode p = betterHashMap.table,
    39                     s = p;
    40             while (s != null){
    41                 System.out.println("key:"+s.k + ", value:" + s.v);
    42                 s = s.next;
    43             }
    44 
    45             System.out.println("打印" +context+ "结束》》》===============");
    46 
    47         }
    48     }
    49 }
    测试代码

    五、测试结果

     1 添加后——limit : 1, capacity : 5
     2 添加后——limit : 2, capacity : 5
     3 添加后——limit : 3, capacity : 5
     4 添加后——limit : 4, capacity : 5
     5 打印put(d-4)开始《《《===============
     6 key:d, value:4
     7 key:c, value:3
     8 key:b, value:2
     9 key:a, value:1
    10 打印put(d-4)结束》》》===============
    11 添加后——limit : 5, capacity : 5
    12 打印put(e-5)开始《《《===============
    13 key:e, value:5
    14 key:d, value:4
    15 key:c, value:3
    16 key:b, value:2
    17 key:a, value:1
    18 打印put(e-5)结束》》》===============
    19 添加后——limit : 5, capacity : 5
    20 ========添加相同的 ‘c’:33 《《 ============
    21 打印put(e-5)开始《《《===============
    22 key:c, value:33
    23 key:e, value:5
    24 key:d, value:4
    25 key:b, value:2
    26 key:a, value:1
    27 打印put(e-5)结束》》》===============
    28 ========添加相同的 ‘c’:33  》》============
    29 添加后——limit : 5, capacity : 5
    30 打印put(f-6)开始《《《===============
    31 key:f, value:6
    32 key:c, value:33
    33 key:e, value:5
    34 key:d, value:4
    35 key:b, value:2
    36 打印put(f-6)结束》》》===============
    37 打印getE开始《《《===============
    38 key:e, value:5
    39 key:f, value:6
    40 key:c, value:33
    41 key:d, value:4
    42 key:b, value:2
    43 打印getE结束》》》===============
    44 
    45 Process finished with exit code 0
    测试结果,实现功能


  • 相关阅读:
    nat下没法ping通virutalbox中的centos7,解决共享文件夹问题
    深度学习的精确率和召回率,浅显的例子
    python发送邮件心得体会
    ubuntu 16.04 搭建tigervnc
    交叉编译7zip过程
    git使用经验汇总
    python 开发环境部署
    Ubuntu设置su和sudo为不需要密码 (摘录自别处)
    ubuntu 16.04 安装wechat, chrome等
    andorid开发build.gradle 增加几种产品的方法
  • 原文地址:https://www.cnblogs.com/bridgestone29-08/p/13070113.html
Copyright © 2011-2022 走看看