博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java集合(十二)Map概括,总结
阅读量:5885 次
发布时间:2019-06-19

本文共 5711 字,大约阅读时间需要 19 分钟。

hot3.png

Java集合(十四)Map对比总结_www.fengfly.com

第1部分 Map概括

Map 是“键值对”映射的抽象接口。

AbstractMap 实现了Map中的绝大部分函数接口。它减少了“Map的实现类”的重复编码。
SortedMap 有序的“键值对”映射接口。
NavigableMap 是继承于SortedMap的,支持导航函数的接口。
HashMap, Hashtable, TreeMap, WeakHashMap这4个类是“键值对”映射的实现类。它们各有区别!

HashMap 是基于“拉链法”实现的散列表。一般用于单线程程序中。

Hashtable 也是基于“拉链法”实现的散列表。它一般用于多线程程序中。
WeakHashMap 也是基于“拉链法”实现的散列表,它一般也用于单线程程序中。相比HashMap,WeakHashMap中的键是“弱键”,当“弱键”被GC回收时,它对应的键值对也会被从WeakHashMap中删除;而HashMap中的键是强键。
TreeMap 是有序的散列表,它是通过红黑树实现的。它一般用于单线程中存储有序的映射。

HashMap和WeakHashMap异同

1 HashMap和WeakHashMap的相同点

1 它们都是散列表,存储的是“键值对”映射。

2 它们都继承于AbstractMap,并且实现Map基础。
3 它们的构造函数都一样。
   它们都包括4个构造函数,而且函数的参数都一样。
4 默认的容量大小是16,默认的加载因子是0.75。
5 它们的“键”和“值”都允许为null。
6 它们都是“非同步的”。

 

2 HashMap和WeakHashMap的不同点

HashMap实现了Cloneable和Serializable接口,而WeakHashMap没有。

   HashMap实现Cloneable,意味着它能通过clone()克隆自己。
   HashMap实现Serializable,意味着它支持序列化,能通过序列化去传输。

HashMap的“键”是“强引用(StrongReference)”,而WeakHashMap的键是“弱引用(WeakReference)”。

   WeakReference的“弱键”能实现WeakReference对“键值对”的动态回收。当“弱键”不再被使用到时,GC会回收它,WeakReference也会将“弱键”对应的键值对删除。
   这个“弱键”实现的动态回收“键值对”的原理呢?其实,通过WeakReference(弱引用)和ReferenceQueue(引用队列)实现的。 首先,我们需要了解WeakHashMap中:
    第一,“键”是WeakReference,即key是弱键。
    第二,ReferenceQueue是一个引用队列,它是和WeakHashMap联合使用的。当弱引用所引用的对象被垃圾回收,Java虚拟机就会把这个弱引用加入到与之关联的引用队列中。 WeakHashMap中的ReferenceQueue是queue。
   第三,WeakHashMap是通过数组实现的,我们假设这个数组是table。
 

接下来,说说“动态回收”的步骤。

(01) 新建WeakHashMap,将“键值对”添加到WeakHashMap中。

        将“键值对”添加到WeakHashMap中时,添加的键都是弱键。
        实际上,WeakHashMap是通过数组table保存Entry(键值对);每一个Entry实际上是一个单向链表,即Entry是键值对链表。
(02) 当某“弱键”不再被其它对象引用,并被GC回收时。在GC回收该“弱键”时,这个“弱键”也同时会被添加到queue队列中。
        例如,当我们在将“弱键”key添加到WeakHashMap之后;后来将key设为null。这时,便没有外部外部对象再引用该了key。
        接着,当Java虚拟机的GC回收内存时,会回收key的相关内存;同时,将key添加到queue队列中。
(03) 当下一次我们需要操作WeakHashMap时,会先同步table和queue。table中保存了全部的键值对,而queue中保存被GC回收的“弱键”;同步它们,就是删除table中被GC回收的“弱键”对应的键值对。
        例如,当我们“读取WeakHashMap中的元素或获取WeakReference的大小时”,它会先同步table和queue,目的是“删除table中被GC回收的‘弱键’对应的键值对”。删除的方法就是逐个比较“table中元素的‘键’和queue中的‘键’”,若它们相当,则删除“table中的该键值对”。

 

3 HashMap和WeakHashMap的比较测试程序

public class CompareHashmapAndWeakhashmap {       public static void main(String[] args) throws Exception {           // 当“弱键”是String时,比较HashMap和WeakHashMap          compareWithString();          // 当“弱键”是自定义类型时,比较HashMap和WeakHashMap          compareWithSelfClass();      }       /**       * 遍历map,并打印map的大小       */     private static void iteratorAndCountMap(Map map) {          // 遍历map          for (Iterator iter = map.entrySet().iterator();                  iter.hasNext();  ) {              Map.Entry en = (Map.Entry)iter.next();              System.out.printf("map entry : %s - %s\n ",en.getKey(), en.getValue());          }           // 打印HashMap的实际大小          System.out.printf(" map size:%s\n\n", map.size());      }       /**       * 通过String对象测试HashMap和WeakHashMap       */     private static void compareWithString() {          // 新建4个String字符串          String w1 = new String("W1");          String w2 = new String("W2");          String h1 = new String("H1");          String h2 = new String("H2");           // 新建 WeakHashMap对象,并将w1,w2添加到 WeakHashMap中          Map wmap = new WeakHashMap();          wmap.put(w1, "w1");          wmap.put(w2, "w2");           // 新建 HashMap对象,并将h1,h2添加到 WeakHashMap中          Map hmap = new HashMap();          hmap.put(h1, "h1");          hmap.put(h2, "h2");           // 删除HashMap中的“h1”。          // 结果:删除“h1”之后,HashMap中只有 h2 !          hmap.remove(h1);           // 将WeakHashMap中的w1设置null,并执行gc()。系统会回收w1          // 结果:w1是“弱键”,被GC回收后,WeakHashMap中w1对应的键值对,也会被从WeakHashMap中删除。          //       w2是“弱键”,但它不是null,不会被GC回收;也就不会被从WeakHashMap中删除。          // 因此,WeakHashMap中只有 w2          // 注意:若去掉“w1=null” 或者“System.gc()”,结果都会不一样!          w1 = null;          System.gc();           // 遍历并打印HashMap的大小          System.out.printf(" -- HashMap --\n");          iteratorAndCountMap(hmap);           // 遍历并打印WeakHashMap的大小          System.out.printf(" -- WeakHashMap --\n");          iteratorAndCountMap(wmap);      }       /**       * 通过自定义类测试HashMap和WeakHashMap       */     private static void compareWithSelfClass() {          // 新建4个自定义对象          Self s1 = new Self(10);          Self s2 = new Self(20);          Self s3 = new Self(30);          Self s4 = new Self(40);                    // 新建 WeakHashMap对象,并将s1,s2添加到 WeakHashMap中          Map wmap = new WeakHashMap();          wmap.put(s1, "s1");          wmap.put(s2, "s2");                    // 新建 HashMap对象,并将s3,s4添加到 WeakHashMap中          Map hmap = new HashMap();          hmap.put(s3, "s3");          hmap.put(s4, "s4");           // 删除HashMap中的s3。          // 结果:删除s3之后,HashMap中只有 s4 !          hmap.remove(s3);           // 将WeakHashMap中的s1设置null,并执行gc()。系统会回收w1          // 结果:s1是“弱键”,被GC回收后,WeakHashMap中s1对应的键值对,也会被从WeakHashMap中删除。          //       w2是“弱键”,但它不是null,不会被GC回收;也就不会被从WeakHashMap中删除。          // 因此,WeakHashMap中只有 s2          // 注意:若去掉“s1=null” 或者“System.gc()”,结果都会不一样!          s1 = null;          System.gc();           /*          // 休眠500ms          try {              Thread.sleep(500);          } catch (InterruptedException e) {              e.printStackTrace();          }          // */                   // 遍历并打印HashMap的大小          System.out.printf(" -- Self-def HashMap --\n");          iteratorAndCountMap(hmap);           // 遍历并打印WeakHashMap的大小          System.out.printf(" -- Self-def WeakHashMap --\n");          iteratorAndCountMap(wmap);      }       private static class Self {           int id;           public Self(int id) {              this.id = id;          }           // 覆盖finalize()方法          // 在GC回收时会被执行          protected void finalize() throws Throwable {              super.finalize();              System.out.printf("GC Self: id=%d addr=0x%s)\n", id, this);          }         }  }

转载于:https://my.oschina.net/zhaoqian/blog/349870

你可能感兴趣的文章
mariadb启动报错:[ERROR] Can't start server : Bind on unix socket: Permission denied
查看>>
nginx的信号量
查看>>
云im php,网易云IM
查看>>
河南农业大学c语言平时作业答案,河南农业大学2004-2005学年第二学期《C语言程序设计》期末考试试卷(2份,有答案)...
查看>>
c语言打开alist文件,C语言 文件的打开与关闭详解及示例代码
查看>>
c语言 中的共用体和结构体如何联合定义,结构体(Struct)、联合体(Union)和位域
查看>>
SDL如何嵌入到QT中?!
查看>>
P1026 统计单词个数
查看>>
[js高手之路] html5 canvas系列教程 - 状态详解(save与restore)
查看>>
poi excel 常用api
查看>>
AD提高动态的方法(附SNR计算)
查看>>
[转]轻松实现可伸缩性,容错性,和负载平衡的大规模多人在线系统
查看>>
五 数组
查看>>
也谈跨域数据交互解决方案
查看>>
EntityFramework中使用Include可能带来的问题
查看>>
面试题28:字符串的排列
查看>>
css important
查看>>
WPF 实现窗体拖动
查看>>
NULL不是数值
查看>>
Oracle学习笔记之五,Oracle 11g的PL/SQL入门
查看>>