源码分析-TreeMap

TreeMap概述

首先TreeMap是实现了NavigableMap和SortMap的Map,从实现的角度说是红黑树。

红黑树

红黑树是平衡搜索树的一种,也是使用最多的一种树,其特点

  • 对于所有的动态集合操作都可以保证以最坏O(lgn)的时间复杂度来运行。
  • 每个节点都包含一个储存位来表示节点的颜色,非红即黑。
  • 通过对任何一条从根节点到叶子节点的简单路径上各个节点的颜色进行约束,红黑树确保没有一条路径会比其他路径长出2倍,而是近似平衡的。

红黑性质:

  1. 每个节点或是红色或是黑色
  2. 根节点是黑色
  3. 每个叶节点是黑色
  4. 如果一个节点是红色,则它的两个子节点都是红色
  5. 对于每个节点,从该节点到其所有后代叶节点的简单路径上,均包含相同数目的黑色节点。

从某节点出发到达一个叶节点的任意一条简单路径上的黑色节点数称为黑高。红黑树的黑高就是其根的黑高。

  • 一棵有n个内部节点的红黑树的高度至多为2lg(n+1)。

相对于其他平衡树,因为他的插入和删除操作只要最多3次左旋或者右旋就可以完成,因此相对于AVL树它的插入和删除效率更高,但由于其不是高度平衡树,其查询效率略低于AVL树。

当然红黑树插入和删除操作是比较复杂的。这里不详细描述等到代码里再说。

静态域和静态方法

静态域:

    private static final boolean RED   = false;
    private static final boolean BLACK = true;

表示红黑节点颜色的bool值。这种用法类似于C++中的宏定义

    private static final Object UNBOUNDED = new Object();

表示对于subMap不可访问的区域。

静态方法

大部分就是获得或者设置节点的域没什么好说的,这里重点说几个有意思的。

  1. computeRedLevel用途不明;
    后续会介绍到。
  2. exportEntry用于返回Entry,但是并不返回TreeMap的节点,而是返回AbstractMap.SimpleImmutableEntry类型。
    static <K,V> Map.Entry<K,V> exportEntry(TreeMap.Entry<K,V> e) {
        return (e == null) ? null :
            new AbstractMap.SimpleImmutableEntry<>(e);
    }

ExportEntry返回一个AbstractMap.SimpleImmutableEntry<>(e)。这很有意思。这个AbstractMap.SimpleImmutableEntry<>(e)是给静态内部类,所以可以单独初始化。

  1. 前驱和后继
    当然前驱和后继的算法是相同的,这里只看一个。
    static <K,V> Entry<K,V> predecessor(Entry<K,V> t) {
        if (t == null)
            return null;
        else if (t.left != null) {
            Entry<K,V> p = t.left;
            while (p.right != null)
                p = p.right;
            return p;
        } else {
            Entry<K,V> p = t.parent;
            Entry<K,V> ch = t;
            while (p != null && ch == p.left) {
                ch = p;
                p = p.parent;
            }
            return p;
        }
    }

先判断t是否为空,如果为空则找t节点的做节点,如果左节点存在则很显然其左节点就是前驱节点,如果左节点为空,则需要向上溯源。直到当前节点是其父节点的右节点,则父节点就是前驱节点。当然这段程序是针对BST来说的。所以所有的BST都可以用类似的方法实现。

内部域
内部域很简单,主要就是root,size,和comparator。其他的内容是由于需要返回视图而设置的。意义也很明显

内部类

Treemap的内部类和之前说HashMap的内部类是类似的,大部分都是为了实现map需要返回视图的要求,或者迭代器的要求来实现的 。

Entry

         K key;
        V value;
        Entry<K,V> left = null;
        Entry<K,V> right = null;
        Entry<K,V> parent;
        boolean color = BLACK;

其他部分的内容并没有什么特别需要说明的,只看下equals和hashCode

        public boolean equals(Object o) {
            if (!(o instanceof Map.Entry))
                return false;
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;

            return valEquals(key,e.getKey()) && valEquals(value,e.getValue());
        }

    static final boolean valEquals(Object o1, Object o2) {
        return (o1==null ? o2==null : o1.equals(o2));
    }

equals先做类型检查,然后仅仅考虑key和value是否相同,然后调用的静态valEquals屏蔽了null和object的区别。

key、value和Entry视图类

类似于HashMap,这几个类都是private的内部类,然后通过一个public方法返回set或者collections类型的视图。通常来说这几个内部类都不实现方

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
以下是Java代码实现: ```java import java.util.Map; import java.util.TreeMap; public class TestStudent { public static void main(String[] args) { Map<Student, String> map = new TreeMap<>((s1, s2) -> s2.getAge() - s1.getAge()); // 按照年龄从大到小排序 map.put(new Student("Tom", "Beijing", 18), "Address1"); map.put(new Student("Jerry", "Shanghai", 20), "Address2"); map.put(new Student("Alice", "Guangzhou", 22), "Address3"); map.put(new Student("Bob", "Shenzhen", 19), "Address4"); map.put(new Student("Lucy", "Hangzhou", 21), "Address5"); for (Map.Entry<Student, String> entry : map.entrySet()) { System.out.println(entry.getKey().toString() + " Address:" + entry.getValue()); } } } class Student { private String name; private String address; private int age; public Student(String name, String address, int age) { this.name = name; this.address = address; this.age = age; } public String getName() { return name; } public String getAddress() { return address; } public int getAge() { return age; } @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", address='" + address + '\'' + ", age=" + age + '}'; } } ``` 输出结果为: ``` Student{name='Alice', address='Guangzhou', age=22} Address:Address3 Student{name='Lucy', address='Hangzhou', age=21} Address:Address5 Student{name='Jerry', address='Shanghai', age=20} Address:Address2 Student{name='Bob', address='Shenzhen', age=19} Address:Address4 Student{name='Tom', address='Beijing', age=18} Address:Address1 ```

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值