TreeMap

文章开头,全家桶少不了。
作为HashMap的好兄弟,TreeMap存在肯定是有的他的理由的。
我看源码喜欢先看JavaDoc
翻译TreeMap的JavaDoc
基于红黑树的NavigableMap实现。 根据映射的键的Comparable或根据映射创建时提供的Comparator对映射进行排序,具体取决于所使用的构造函数。
此实现为containsKey,get,put和remove操作提供了保证的log(n)时间成本。算法是对Cormen,Leiserson和Rivest的<<算法简介>>中的算法的改编。
请注意,与任何已排序的映射一样,树映射所维护的顺序以及是否提供显式比较器,必须与equals是正确的实现Map接口。具体请参见Comparable或Comparator,以精确了解与equals一致的。之所以这样,是因为Map接口是根据equals操作的,但是排序的映射使用其compareTo或compare方法执行所有键比较,此方法视为相等的两个键是排序后的Map。排序后的映射的行为是明确定义的,即使其顺序与equals不匹配;它只是无法遵守Map接口的一般合同。
查看TreeMap的继承图
也就是说所有基本的CRUD操作其实都是和Map一样的,所以就不详细写了,主要还是写一些这个的应用场景以及使用的注意点,以及他的特点。

首先TreeMap是基于红黑树来实现的,那就顺带复习一下红黑树好了。

红黑树规则特点:

  1. 节点分为红色或者黑色;
  2. 根节点必为黑色;
  3. 叶子节点都为黑色,且为null;
  4. 连接红色节点的两个子节点都为黑色(红黑树不会出现相邻的红色节点);
  5. 从任意节点出发,到其每个叶子节点的路径中包含相同数量的黑色节点;
  6. 新加入到红黑树的节点为红色节点;

红黑树自平衡基本操作:

  1. 变色:在不违反上述红黑树规则特点情况下,将红黑树某个node节点颜色由红变黑,或者由黑变红;
  2. 左旋:逆时针旋转两个节点,让一个节点被其右子节点取代,而该节点成为右子节点的左子节点
  3. 右旋:顺时针旋转两个节点,让一个节点被其左子节点取代,而该节点成为左子节点的右子节点

TreeMap的特点
  • TreeMap实现了NavigableMap接口,而NavigableMap接口继承着SortedMap接口,致使我们的TreeMap是有序的!如果没有实现comparator,默认按照key的自然顺序排序。如果在构造方法中传递了Comparator对象,那么就会按照Comparator的方法进行比较值得说明的是:如果使用的是compareTo(T o)方法来比较,key一定是不能为null,并且得实现了Comparable接口的。即使是传入了Comparator对象,不用compareTo(T o)方法来比较,key也是不能为null的
  • 由于底层是红黑树,那么时间复杂度可以保证为log(n)这个理论的介绍可以看https://blog.csdn.net/JERRY_PRI/article/details/8959426?utm_source=blogxgwz1
  • key不能为null,为null为抛出NullPointException的,但是如果硬要为null就是在构造的时候用自己的Comparator
  • 想要自定义比较,在构造方法中传入Comparator对象,否则使用key的自然排序来进行比较
  • TreeMap非同步的,想要同步可以使用Collections来进行封装

TreeMap的使用场景
这其实也认为是红黑树的使用场景
  1. 红黑树是牺牲了严格的高度平衡的优越条件为代价,它只要求部分地达到平衡要求,降低了对旋转的要求,从而提高了性能。
  2. 红黑树能够以O(log2 n)的时间复杂度进行搜索、插入、删除操作。此外,由于它的设计,任何不平衡都会在三次旋转之内解决。当然,还有一些更好的,但实现起来更复杂的数据结构能够做到一步旋转之内达到平衡,但红黑树能够给我们一个比较“便宜”的解决方案。
  3. TreeMap 实现了 SortMap 接口,其能够根据键排序,默认是按键的升序排序,也可以指定排序的比较器,当用 Iterator 遍历 TreeMap 时得到的记录是排过序的,TreeMap 取出来的是排序后的键值
  4.  红黑树占用的内存更小(仅需要为其存在的节点分配内存),而Hash事先应该分配足够的内存存储散列表,即使有些槽可能弃用。

TreeMap的注意点
红黑树是以 key 来进行排序的,所以这里以 key 来进行比较检索出合适的叶子结点,而比较多依据就是 Comparator 或者 Comparable ,如果比较出来的结果是 0,那么后面的 value 会覆盖前面的 value。所以在使用 Map 的时候,一定要注意底层的数据结构和对 key 的处理方式。
posted @ 2020-06-24 16:05  smartcat994  阅读(257)  评论(0编辑  收藏  举报