java源码分析05-TreeMap
2015-11-10 18:21
471 查看
说什么王权富贵,坚持!
今天,我们来看下TreeMap集合。作为Map集合中的一员大将,她的职责还是很大的,
除了常见的存储键值对和快速查找,她还有很多技能,例如有序的迭代序列,范围查找...,那么,她
到底是怎么拥有这么大的魅力的呢?我迫不及待地想深入了解她。
范围查找让我们想到了Mysql中的limit或者Oracle中的rownum的使用方法,例如查找某段时间内的
记录等
1.类结构
![](http://img.blog.csdn.net/20151110165345070?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
![](http://img.blog.csdn.net/20151110165456369?watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQv/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center)
2.内部结构解析
构造器
上述代码表名:第一,如果没有传入比较器,那么会采用默认的比较器;第二,如果传入了比较器,则
按照自定义的方式排序。默认的比较器是自然顺序,例如1,2,3...或者按照字母顺序排列。第三,如果传入的
是已排序的Map,首先获取她的比较器实例。
增删改查
形式(红黑树),通过比较器来判断存储在左子节点还是右子节点;第三,节点的查询也是通过
树的遍历,由于是二叉排序树,所以根据比较器来判断是在左子节点还是右子节点;
左子节点为空。
弹出首节点,首先找到第一个结点,
获取map集合,包括升序和降序方式
如果弹出第一个结点,不仅仅包含删除第一个节点,还需要使红黑树达到新的平衡。
范围查找
红黑树
TreeMap采用红黑树结构,这是一种自平衡二叉树。
左旋
今天,我们来看下TreeMap集合。作为Map集合中的一员大将,她的职责还是很大的,
除了常见的存储键值对和快速查找,她还有很多技能,例如有序的迭代序列,范围查找...,那么,她
到底是怎么拥有这么大的魅力的呢?我迫不及待地想深入了解她。
范围查找让我们想到了Mysql中的limit或者Oracle中的rownum的使用方法,例如查找某段时间内的
记录等
1.类结构
public class TreeMap<K,V> extends AbstractMap<K,V> implements NavigableMap<K,V>, Cloneable, java.io.Serializable
2.内部结构解析
构造器
public TreeMap() { comparator = null; } public TreeMap(Comparator<? super K> comparator) { this.comparator = comparator; } public TreeMap(Map<? extends K, ? extends V> m) { comparator = null; putAll(m); } public TreeMap(SortedMap<K, ? extends V> m) { comparator = m.comparator(); try { buildFromSorted(m.size(), m.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } }
上述代码表名:第一,如果没有传入比较器,那么会采用默认的比较器;第二,如果传入了比较器,则
按照自定义的方式排序。默认的比较器是自然顺序,例如1,2,3...或者按照字母顺序排列。第三,如果传入的
是已排序的Map,首先获取她的比较器实例。
public void putAll(Map<? extends K, ? extends V> map) { int mapSize = map.size(); if (size==0 && mapSize!=0 && map instanceof SortedMap) { Comparator c = ((SortedMap)map).comparator(); if (c == comparator || (c != null && c.equals(comparator))) { ++modCount; try { buildFromSorted(mapSize, map.entrySet().iterator(), null, null); } catch (java.io.IOException cannotHappen) { } catch (ClassNotFoundException cannotHappen) { } return; } } super.putAll(map); }
增删改查
public V get(Object key) { Entry<K,V> p = getEntry(key); return (p==null ? null : p.value); }
final Entry<K,V> getEntry(Object key) { // Offload comparator-based version for sake of performance if (comparator != null) return getEntryUsingComparator(key); if (key == null) throw new NullPointerException(); Comparable<? super K> k = (Comparable<? super K>) key; Entry<K,V> p = root; while (p != null) { int cmp = k.compareTo(p.key); if (cmp < 0) p = p.left; else if (cmp > 0) p = p.right; else return p; } return null; }上述代码告诉我们,第一,key不为空,否则抛出空指向异常;其次,节点的存储采用树的
形式(红黑树),通过比较器来判断存储在左子节点还是右子节点;第三,节点的查询也是通过
树的遍历,由于是二叉排序树,所以根据比较器来判断是在左子节点还是右子节点;
public boolean containsKey(Object key) { return getEntry(key) != null; }是否包含也是通过getEntry方法来判断。
final Entry<K,V> getFirstEntry() { Entry<K,V> p = root; if (p != null) while (p.left != null) p = p.left; return p; }第一个结点的获取,通过查找根节点的左子节点,并且一直查找左子节点,直到该节点的
左子节点为空。
/** * @since 1.6 */ public Map.Entry<K,V> pollFirstEntry() { Entry<K,V> p = getFirstEntry(); Map.Entry<K,V> result = exportEntry(p); if (p != null) deleteEntry(p); return result; }
弹出首节点,首先找到第一个结点,
public Set<K> keySet() { return navigableKeySet(); }
public NavigableSet<K> navigableKeySet() { KeySet<K> nks = navigableKeySet; return (nks != null) ? nks : (navigableKeySet = new KeySet(this)); }
public NavigableSet<K> descendingKeySet() { return descendingMap().navigableKeySet(); }
获取map集合,包括升序和降序方式
public Map.Entry<K,V> pollFirstEntry() { Entry<K,V> p = getFirstEntry(); Map.Entry<K,V> result = exportEntry(p); if (p != null) deleteEntry(p); return result; }
/** * Delete node p, and then rebalance the tree. */ private void deleteEntry(Entry<K,V> p) { modCount++; size--; // If strictly internal, copy successor's element to p and then make p // point to successor. if (p.left != null && p.right != null) { Entry<K,V> s = successor(p); p.key = s.key; p.value = s.value; p = s; } // p has 2 children // Start fixup at replacement node, if it exists. Entry<K,V> replacement = (p.left != null ? p.left : p.right); if (replacement != null) { // Link replacement to parent replacement.parent = p.parent; if (p.parent == null) root = replacement; else if (p == p.parent.left) p.parent.left = replacement; else p.parent.right = replacement; // Null out links so they are OK to use by fixAfterDeletion. p.left = p.right = p.parent = null; // Fix replacement if (p.color == BLACK) fixAfterDeletion(replacement); } else if (p.parent == null) { // return if we are the only node. root = null; } else { // No children. Use self as phantom replacement and unlink. if (p.color == BLACK) fixAfterDeletion(p); if (p.parent != null) { if (p == p.parent.left) p.parent.left = null; else if (p == p.parent.right) p.parent.right = null; p.parent = null; } } }
如果弹出第一个结点,不仅仅包含删除第一个节点,还需要使红黑树达到新的平衡。
范围查找
public SortedMap<K,V> subMap(K fromKey, K toKey) { return subMap(fromKey, true, toKey, false); }
public NavigableMap<K,V> subMap(K fromKey, boolean fromInclusive, K toKey, boolean toInclusive) { return new AscendingSubMap(this, false, fromKey, fromInclusive, false, toKey, toInclusive); }
public SortedMap<K,V> headMap(K toKey) { return headMap(toKey, false); }
public SortedMap<K,V> tailMap(K fromKey) { return tailMap(fromKey, true); }
红黑树
// Red-black mechanics private static final boolean RED = false; private static final boolean BLACK = true; /** * Node in the Tree. Doubles as a means to pass key-value pairs back to * user (see Map.Entry). */ static final class Entry<K,V> implements Map.Entry<K,V> { K key; V value; Entry<K,V> left = null; Entry<K,V> right = null; Entry<K,V> parent; boolean color = BLACK; /** * Make a new cell with given key, value, and parent, and with * {@code null} child links, and BLACK color. */ Entry(K key, V value, Entry<K,V> parent) { this.key = key; this.value = value; this.parent = parent; }
TreeMap采用红黑树结构,这是一种自平衡二叉树。
/** From CLR */ private void rotateLeft(Entry<K,V> p) { if (p != null) { Entry<K,V> r = p.right; p.right = r.left; if (r.left != null) r.left.parent = p; r.parent = p.parent; if (p.parent == null) root = r; else if (p.parent.left == p) p.parent.left = r; else p.parent.right = r; r.left = p; p.parent = r; } }
左旋
相关文章推荐
- java使用socket上传文件,实现server端和client端
- JAVA静态引入
- servlet页面中文乱码或是问号
- 第一个Servlet
- 【Java】HashMap 和 HashTable 的区别到底是什么?
- JavaSript模块规范 - AMD规范与CMD规范介绍
- JAVA打印正弦图形
- Java并发编程(六) 一个日志服务的例子
- Java RC4 加密解密
- Mybatis3.x与Spring4.x整合
- Jni 两种方法打开底层文件返回FD给Java
- java插入字符串
- java插入字符串
- JavaBean--JavaBean与表单
- 通过Spring配置文件中bean中的property赋值
- 【leetcode】Maximum Subarray
- Java中subList的问题
- Spring注解详解
- java实现定时任务的三种方法
- Eclipse中开发测试脚本