当前位置:   article > 正文

源码解析java集合框架,TreeMap源码_comparable k = (comparable)

comparable k = (comparable) key;

一、TreeMap剖析

TreeMap是Map接口下一个实现类,基于键值对来存储每个数据,TreeMap是一个有序集合,顺序是key值的插入顺序,每个元素对象必须实现比较器,底层数据结构是一颗红黑树,之前在介绍HashMap时也有提到过红黑树,HashMap底层是数组链表红黑树,而TreeMap只包含红黑树一种数据结构类型。红黑树插入、检索、移除元素操作时间复杂度都是O(logn),性能较高。

红黑树,TreeMap数据结构

 

TreeMap树中每个节点都是一个Entry<K,V>对象,Entry是TreeMap类中的内部类,Entry包含的属性有键值K key,值V value,左子树Entry<K,V> left,右子树Entry<K,V> right,父节点Entry<K,V> parent,颜色属性boolean color。

TreeMap节点Entry

 

 

二、源码解读

2.1 构造方法

  1. public TreeMap() {
  2. comparator = null;
  3. }
  4. public TreeMap(Comparator<? super K> comparator) {
  5. this.comparator = comparator;
  6. }

TreeMap构造方法只是对比较器comparator赋值,没有其他新建操作。

 

2.2 TreeMap添加元素,put(k,v)方法

  1. public V put(K key, V value) {
  2. Entry<K,V> t = root; //根节点
  3. if (t == null) { //如果根节点为空,则把当前数据放在根节点
  4. compare(key, key); // type (and possibly null) check
  5. root = new Entry<>(key, value, null); //新建Entry赋值给根root
  6. size = 1;
  7. modCount++;
  8. return null;
  9. }
  10. int cmp;
  11. Entry<K,V> parent;
  12. // split comparator and comparable paths
  13. Comparator<? super K> cpr = comparator; //外部比较器
  14. //如果存在外部比较器,就使用外部比较器比较key大小
  15. //确定存放位置在左子树、右子树还是覆盖根节点的值
  16. if (cpr != null) {
  17. do { //迭代整个树
  18. parent = t;
  19. cmp = cpr.compare(key, t.key);
  20. if (cmp < 0) //key小,放于左子树
  21. t = t.left;
  22. else if (cmp > 0) //key大,放于右子树
  23. t = t.right;
  24. else //与根节点key值相等,则覆盖根节点value值
  25. return t.setValue(value);
  26. } while (t != null);
  27. }
  28. else {
  29. if (key == null)
  30. throw new NullPointerException();
  31. @SuppressWarnings("unchecked")
  32. Comparable<? super K> k = (Comparable<? super K>) key;
  33. do { //迭代整个树
  34. parent = t;
  35. cmp = k.compareTo(t.key);
  36. if (cmp < 0)
  37. t = t.left;
  38. else if (cmp > 0)
  39. t = t.right;
  40. else
  41. return t.setValue(value);
  42. } while (t != null);
  43. }
  44. //比较完,找到要插入位置的parent
  45. Entry<K,V> e = new Entry<>(key, value, parent);
  46. if (cmp < 0) //放在parent的左子树
  47. parent.left = e;
  48. else //放在parent的右子树
  49. parent.right = e;
  50. //修复,红黑树的左旋、右旋,保证树的平衡
  51. fixAfterInsertion(e);
  52. size++;
  53. modCount++;
  54. return null;
  55. }

TreeMap添加元素就是不断的比较key大小的过程,最终找到key相等或者相对应存放位置,红黑树添加元素后会有个自平衡的操作,利用左旋右旋来保持树的平衡。

 

2.3 TreeMap获取元素,get(k)方法

  1. public V get(Object key) {
  2. Entry<K,V> p = getEntry(key);
  3. return (p==null ? null : p.value);
  4. }
  1. final Entry<K,V> getEntry(Object key) {
  2. if (comparator != null)
  3. return getEntryUsingComparator(key);
  4. if (key == null)
  5. throw new NullPointerException();
  6. @SuppressWarnings("unchecked")
  7. Comparable<? super K> k = (Comparable<? super K>) key;
  8. Entry<K,V> p = root;
  9. while (p != null) { //p为当前搜索的根节点,动态赋值
  10. int cmp = k.compareTo(p.key);
  11. //传入key与当前根节点key对比,相等则当前根节点就为查询的数据
  12. //传入key小,则进入根的左子树,继续迭代
  13. //传入key大,则进入根的右子树,继续迭代
  14. if (cmp < 0)
  15. p = p.left;
  16. else if (cmp > 0)
  17. p = p.right;
  18. else
  19. return p;
  20. }
  21. return null; //迭代完,没有找到,返回空
  22. }

get(k)方法传入查询key参数,查找算法中使用key值与树中每个节点key对比,根据大小选择根节点、左子树、右子树。

 

2.4 TreeMap移除元素,remove(k)方法

  1. public V remove(Object key) {
  2. Entry<K,V> p = getEntry(key); //根据key查找到节点
  3. if (p == null)
  4. return null;
  5. V oldValue = p.value;
  6. deleteEntry(p); //从树中删除节点,树自平衡
  7. return oldValue;
  8. }

 

TreeMap底层就是一颗红黑树,每个节点都是key-value键值对,检索、添加元素效率较高,且元素有保持有序,与HashMap相比,TreeMap性能稍微低一点,但HashMap元素无序。一般在需要排序的map中使用TreeMap。

 

 

 

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家自动化/article/detail/885396
推荐阅读
相关标签
  

闽ICP备14008679号