明天尝试刨一下TreeMap的祖坟。

底层构造比照

先来看一下与HashMap、LinkedHashMap的比照,同时就当是温习一下:

  1. HashMap应用数组存储数据,并应用单向链表构造存储hash抵触数据,同一个抵触桶中数据量大的时候(默认超过8)则应用红黑树存储抵触数据。
  2. LinkedHashMap应用数组+双向链表存储数据,抵触数据存储形式同HashMap。
  3. TreeMap应用红黑树存储数据,留神是间接应用红黑树,不应用table数组。

对于排序个性

  1. HashMap无程序,不能放弃程序。
  2. LinkedHashMap能放弃写入的程序,遍历的时候能够依照写入程序获取数据。
  3. TreeMap是有序的Map,主动依照key值排序存储,遍历时获取到的是有序数据。

须要留神LinkedHashMap和TreeMap在程序方面的区别,LinkedHashMap只能放弃写入程序,从“排序”的角度讲,他理论是无序的。

只有TreeMap是能够实现主动排序的。

TreeMap依照什么排序?

TreeMap底层反对两种排序形式:

  1. TreeMap对象实例化时传入comparator对象。
  2. key值对象实现Comparable接口。

如果以上两点都不能满足的话,向TreeMap对象put数据的时候会抛出运行时异样。

比方TreeMap<String,Object>,因为String实现了Comparable接口,所以是没有问题的。

然而如果自定义的对象,没有实现Comparable接口,同时在TreeMap实例化的时候没有设置comparator对象,则该TreeMap对象理论是不可用的。

TreeMap是否能够存储null?

指的是,是否能够存储key为空的数据?咱们晓得HashMap是能够反对惟一一个null对象的。

很多人都说不能够,然而我感觉有条件能够,尽管还没有测试。

条件是实例化TreeMap对象的时候指定comparator对象,同时,该comparator对象的compare办法能够反对null。

钻研TreeMap的put源码,也能够发现对以上说法的反对:

Comparator<? super K> cpr = comparator;        if (cpr != null) {            do {                parent = t;                cmp = cpr.compare(key, t.key);                if (cmp < 0)                    t = t.left;                else if (cmp > 0)                    t = t.right;                else                    return t.setValue(value);            } while (t != null);        }        else {            if (key == null)                throw new NullPointerException();            ...省略若干代码

能够发现如果有comparator的话,put办法不会立刻抛出异样。然而如果comparator对象的compare办法不能反对null的话,一样会抛出异样。

put办法

因为TreeMap反对主动排序,所以put办法会查看是否满足规定。

不满足排序规定,抛出异样。

否则,依照红黑树算法规定要求,创立红黑树,存储数据。

get办法

依据红黑树查找算法查找并返回数据,红黑树是均衡二叉树,查问工夫复杂度为O(log(n))。

key遍历

比方调用TreeMap.keySet办法,采纳遍历二叉树算法,依照从小到大的程序返回所有key值组成的循环器。

我该应用哪一个?

须要用到Map的时候,到底该应用哪一个的问题:

  1. 我只须要一个存储数据的容器,没有具体要求的话,用HashMap。
  2. 存储数据后,有依照存储程序获取数据的需要,采纳LinkedHashMap。
  3. 心愿存储数据的同时,帮忙实现主动排序,采纳TreeMap。

性能的问题,其实简直不须要思考,不过咱们还是须要晓得:

  1. HashMap和LinkedHashMap查问速度快,现实状况下工夫复杂度简直是O(1)。
  2. HashMap写入速度最快,LinkedHashMap写入速度与HashMap简直雷同,TreeMap写入速度最慢(实践上,理论数据量小的状况下未必慢)。
  3. 遍历速度相差无几,实践上HashMap会慢一点,因为须要遍历空桶。

并发问题尚待钻研,然而咱们分明地晓得,以上三种均不具备线程安全性。

好梦!