java - TreeMap
特点
- TreeMap 是一个有序的key-value集合,它是通过红黑树实现的。
- TreeMap 继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。
- TreeMap 实现了NavigableMap接口,意味着它支持一系列的导航方法。比如返回有序的key集合。
- TreeMap 基于红黑树(Red-Black tree)实现。该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法。
- TreeMap 非同步,所以它的iterator方法返回的迭代器是fail-fastl的。
扩容
由于TreeMap是基于红黑树的,其根本实现是链表,所以容量是根据增加元素而动态加一。
TreeMap 和 TreeSet是同样的。
TreeMap的构造函数
// 默认构造函数。使用该构造函数,TreeMap中的元素按照自然排序进行排列。 TreeMap() // 创建的TreeMap包含Map TreeMap(Map<? extends K, ? extends V> copyFrom) // 指定Tree的比较器 TreeMap(Comparator<? super K> comparator) // 创建的TreeSet包含copyFrom TreeMap(SortedMap<K, ? extends V> copyFrom)
TreeMap的API
Entry<K, V> ceilingEntry(K key) K ceilingKey(K key) void clear() Object clone() Comparator<? super K> comparator() boolean containsKey(Object key) NavigableSet<K> descendingKeySet() NavigableMap<K, V> descendingMap() Set<Entry<K, V>> entrySet() Entry<K, V> firstEntry() K firstKey() Entry<K, V> floorEntry(K key) K floorKey(K key) V get(Object key) NavigableMap<K, V> headMap(K to, boolean inclusive) SortedMap<K, V> headMap(K toExclusive) Entry<K, V> higherEntry(K key) K higherKey(K key) boolean isEmpty() Set<K> keySet() Entry<K, V> lastEntry() K lastKey() Entry<K, V> lowerEntry(K key) K lowerKey(K key) NavigableSet<K> navigableKeySet() Entry<K, V> pollFirstEntry() Entry<K, V> pollLastEntry() V put(K key, V value) V remove(Object key) int size() SortedMap<K, V> subMap(K fromInclusive, K toExclusive) NavigableMap<K, V> subMap(K from, boolean fromInclusive, K to, boolean toInclusive) NavigableMap<K, V> tailMap(K from, boolean inclusive) SortedMap<K, V> tailMap(K fromInclusive)
数据结构
TreeMap的本质是R-B Tree(红黑树),它包含几个重要的成员变量: root, size, comparator。
- root 是红黑树的根节点。它是Entry类型,Entry是红黑树的节点,它包含了红黑树的6个基本组成成分:key(键)、value(值)、left(左孩子)、right(右孩子)、parent(父节点)、color(颜色)。Entry节点根据key进行排序,Entry节点包含的内容为value。
- comparator 红黑数排序时,根据Entry中的key进行排序;Entry中的key比较大小是根据比较器comparator来进行判断的。
- size 是红黑数中节点的个数。
红黑树简介
红黑树又称红-黑二叉树,它首先是一颗二叉树,它具体二叉树所有的特性。同时红黑树更是一颗自平衡的排序二叉树。
我们知道一颗基本的二叉树他们都需要满足一个基本性质--即树中的任何节点的值大于它的左子节点,且小于它的右子节点。按照这个基本性质使得树的检索效率大大提高。我们知道在生成二叉树的过程是非常容易失衡的,最坏的情况就是一边倒(只有右/左子树),这样势必会导致二叉树的检索效率大大降低(O(n)),所以为了维持二叉树的平衡,大牛们提出了各种实现的算法,如:AVL,SBT,伸展树,TREAP ,红黑树等等。
平衡二叉树必须具备如下特性:它是一棵空树或它的左右两个子树的高度差的绝对值不超过1,并且左右两个子树都是一棵平衡二叉树。也就是说该二叉树的任何一个等等子节点,其左右子树的高度都相近。
红黑树特点
- 每个节点都只能是红色或者黑色
- 根节点是黑色
- 每个叶节点(NIL节点,空节点)是黑色的。
- 如果一个结点是红的,则它两个子节点都是黑的。也就是说在一条路径上不能出现相邻的两个红色结点。
- 从任一节点到其每个叶子的所有路径都包含相同数目的黑色节点。
说白了,红黑树就是让数据的查找、插入、删除更高效,其检索效率为O(log n)
红黑树学习文章
性能问题
在性能上,TreeMap由于要排序,所以插入和删除要比HashMap慢一点,但是如果key是自然顺序或自定义顺序,其实性能上会更好点。
TreeMap遍历方法
TreeMap有顺序遍历和逆序遍历
顺序遍历
Iterator<K> keyIterator() { return new KeyIterator(getFirstEntry()); }
final class KeyIterator extends PrivateEntryIterator<K> { KeyIterator(Entry<K,V> first) { super(first); } public K next() { return nextEntry().key; } }
逆序遍历
Iterator<K> descendingKeyIterator() { return new DescendingKeyIterator(getLastEntry()); }
final class DescendingKeyIterator extends PrivateEntryIterator<K> { DescendingKeyIterator(Entry<K,V> first) { super(first); } public K next() { return prevEntry().key; } }
其它遍历一
// 假设map是TreeMap对象 // map中的key是String类型,value是Integer类型 Integer integ = null; Iterator iter = map.entrySet().iterator(); while(iter.hasNext()) { Map.Entry entry = (Map.Entry)iter.next(); // 获取key key = (String)entry.getKey(); // 获取value integ = (Integer)entry.getValue(); }
其它遍历二
// 假设map是TreeMap对象 // map中的key是String类型,value是Integer类型 String key = null; Integer integ = null; Iterator iter = map.keySet().iterator(); while (iter.hasNext()) { // 获取key key = (String)iter.next(); // 根据key,获取value integ = (Integer)map.get(key); }
其它遍历三
// 假设map是TreeMap对象 // map中的key是String类型,value是Integer类型 Integer value = null; Collection c = map.values(); Iterator iter= c.iterator(); while (iter.hasNext()) { value = (Integer)iter.next(); }