java8 TreeMap接口实现源码解析

本文详细介绍了Java8中的TreeMap,包括它作为SortedMap和NavigableMap接口的实现,讲解了SortedMap和NavigableMap的主要方法及使用场景。内容涵盖TreeMap的构造、红黑树节点实现、元素插入与查找、范围查找、子Map获取以及视图方法。文章深入源码,解析了TreeMap的内部工作原理,特别是buildFromSorted方法的递归实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、类继承图

二、SortedMap接口概述和使用

       SortedMap表示一个维护了key的顺序的Map,通过key本身实现的Comparable接口或者SortedMap实例初始化时指定Comparator实例来排序。如果插入的key没有实现Comparable接口,也不能被Comparator实例比较,则会抛出异ClassCastException。注意实现Comparable或者Comparator接口时,应保证与key的equals()方法保持一致,即equals()方法相等时,通过Comparable或者Comparator比较的结果也应该是相等的,因为equals()方法是Map接口判断key相等的基础。

接口包含的方法如下:

SortedMap覆写了Map接口中keySet(),values(),entrySet()的方法定义,增加了一条,要求返回的视图中的元素时按照键值K升序排序的。其他方法的使用参考示例:

public class User {
    private String userName;

    private Integer age;

    public User() {
    }

    public User(String userName, Integer age) {
        this.userName = userName;
        this.age = age;
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                '}';
    }
}

public class UserComp implements Comparable<UserComp> {
    private String userName;

    private Integer age;

    public UserComp() {
    }

    public UserComp(String userName, Integer age) {
        this.userName = userName;
        this.age = age;
    }

    //注意此处是this-o,如果反过来排序就是降序的
    public int compareTo(UserComp o) {
        return this.age-o.getAge();
    }

    public String getUserName() {
        return userName;
    }

    public void setUserName(String userName) {
        this.userName = userName;
    }

    public Integer getAge() {
        return age;
    }

    public void setAge(Integer age) {
        this.age = age;
    }

    @Override
    public String toString() {
        return "User{" +
                "userName='" + userName + '\'' +
                ", age=" + age +
                '}';
    }
}

@Test
    public void name() throws Exception {
        //String实现了Comparable接口
        SortedMap<String,Integer> sortedMap=new TreeMap();
        sortedMap.put("a",1);
        sortedMap.put("c",1);
        sortedMap.put("b",1);
        for(String key:sortedMap.keySet()){
            System.out.println(key+":"+sortedMap.get(key));
        }
    }


    @Test
    public void test3() throws Exception {
        //初始化时提供Comparator接口实现
        Comparator<User> comparator=new Comparator<User>() {
            //注意如果o2-o1,结果就是降序了
            public int compare(User o1, User o2) {
                return o1.getAge()-o2.getAge();
            }
        };
        SortedMap<User,Integer> sortedMap=new TreeMap(comparator);
        sortedMap.put(new User("shl",12),1);
        sortedMap.put(new User("shl",13),1);
        sortedMap.put(new User("shl",14),1);
        for(User key:sortedMap.keySet()){
            System.out.println(key+":"+sortedMap.get(key));
        }
    }

    @Test
    public void test4() throws Exception {
        //UserComp实现了Comparable接口
        SortedMap<UserComp,Integer> sortedMap=new TreeMap();
        sortedMap.put(new UserComp("shl",12),1);
        sortedMap.put(new UserComp("shl",13),1);
        sortedMap.put(new UserComp("shl",14),1);
        for(UserComp key:sortedMap.keySet()){
            System.out.println(key+":"+sortedMap.get(key));
        }
    }

    @Test
    public void test5() throws Exception {
        SortedMap<Integer,String> sortedMap=new TreeMap();
        sortedMap.put(1,"a");
        sortedMap.put(2,"a");
        sortedMap.put(3,"a");
        sortedMap.put(4,"a");
        sortedMap.put(5,"a");
        sortedMap.put(6,"a");
        //SortedMap返回子Map时都是半包含的,即包含最小值不包含最大值,NavigableMap中可以指定是否起止值
        //返回大于等于1,小于4的子Map
        System.out.println("========subMap========");
        SortedMap<Integer,String> subMap=sortedMap.subMap(1,4);
        for(Integer key:subMap.keySet()){
            System.out.println(key+":"+subMap.get(key));
        }
        //返回小于5的子Map
        System.out.println("========headMap========");
        subMap=sortedMap.headMap(5);
        for(Integer key:subMap.keySet()){
            System.out.println(key+":"+subMap.get(key));
        }
        //返回大于等于2的子Map
        System.out.println("========tailMap========");
        subMap=sortedMap.tailMap(2);
        for(Integer key:subMap.keySet()){
            System.out.println(key+":"+subMap.get(key));
        }
        System.out.println("firstKey:"+subMap.firstKey());
        System.out.println("lastKey:"+subMap.lastKey());
    }

三、NavigableMap接口概述和使用

      NavigableMap扩展自SortedMap,增加了一些查找目标key的快捷方法,比如lowerEntry返回小于,floorEntry返回小于或者等于, ceilingEntry返回大于或等于,higherEntry返回大于给定key的Map.Entry对象。类似的有lowerKey,floorKey,ceilingKey, higherKey返回符合条件的目标key。扩展了SortedMap的subMap,headMap,tailMap等方法,增加参数可以指定是否包含起止值,且返回的是SortedMap的升级接口NavigableMap实例。增加对降序遍历的支持,通过descendingMap()返回一个降序排序的视图,注意默认的升序视图的遍历比降序视图要快。接口包含的方法如下:

参考如下示例:

 @Test
    public void test() throws Exception {
        NavigableMap<Integer,String> sortedMap=new TreeMap();
        sortedMap.put(1,"a");
        sortedMap.put(2,"a");
        sortedMap.put(3,"a");
        sortedMap.put(4,"a");
        sortedMap.put(5,"a");
        sortedMap.put(6,"a");
        //小于指定key的最大的一个key
        Map.Entry<Integer,String> entry=sortedMap.lowerEntry(3);
        System.out.println(entry);
        //小于或等于指定key的最大的一个key
        entry=sortedMap.floorEntry(3);
        System.out.println(entry);
        //大于指定key的最小的一个key
        entry=sortedMap.higherEntry(3);
        System.out.println(entry);
        //大于等于指定key的最小的一个key
        entry=sortedMap.ceilingEntry(3);
        System.out.println(entry);
        //返回并移除第一个元素
        Map.Entry first=sortedMap.pollFirstEntry();
        System.out.println(first.getKey());
        //返回并移除最后一个元素
        Map.Entry last=sortedMap.pollLastEntry();
        System.out.println(last.getKey());
        //表示不包含2,包含5
        NavigableMap<Integer,String> subMap= sortedMap.subMap(2,false,5 ,true);
        for(Integer key:subMap.keySet()){
            System.out.println("key="+key+",value="+subMap.get(key));
        }
    }

    @Test
    public void test2() throws Exception {
        NavigableMap<Integer,String> sortedMap=new TreeMap();
        sortedMap.put(1,"a");
        sortedMap.put(2,"a");
        sortedMap.put(3,"a");
        sortedMap.put(4,"a");
        sortedMap.put(5,"a");
        sortedMap.put(6,"a");
        //默认是升序
        for(Integer key:sortedMap.keySet()){
            System.out.println(key+":"+sortedMap.get(key));
        }
        //返回降序排列的key视图
        NavigableMap<Integer,String> desMap=sortedMap.descendingMap();
        for(Integer key:desMap.keySet()){
            System.out.println(key+":"+sortedMap.get(key));
        }
        //效果等同于descendingMap
        for(Integer key:sortedMap.descendingKeySet()){
            System.out.println(key+":"+sortedMap.get(key));
        }
    }

四、TreeMap接口实现源码解读

     TreeMap是一个基于红黑树结构的NavigableMap接口实现,因为key必须可比,所以key不能是null,value可以是null。同HashMap,非线程安全,遍历时修改元素会快读失败。

1、全局属性

   //用于比较K顺序,如果K实现了Comparable接口,可以为null
    private final Comparator<? super K> comparator;

    //红黑树的根节点
    private transient Entry<K,V> root;

   //节点个数
    private transient int size = 0;

    //修改次数
    private transient int modCount = 0;

    //节点颜色
    private static final boolean RED   = false;
    private static final boolean BLACK = true;

    //视图属性
    private transient EntrySet entrySet;
    private transient KeySet<K> navigableKeySet;
    private transient NavigableMap<K,V> descendingMap;

    //表示无上限的常量
    private static final Object UNBOUNDED = new Object();

2、构造方法

    public TreeMap() {
        comparator = null;
    }

    public TreeMap(Comparator<? super K> comparator) {
        this.comparator = comparator;
    }

    public TreeMap(Map<? extends K, ? extends V> m) {
        comparator = null;
        //判断m是否是SortedMap实例,如果是利用buildFromSorted方法初始化,否则将Map中键值对逐一put到TreeMap中
        putAll(m);
    }

    public TreeMap(SortedMap<K, ? extends V> m) {
        comparator = m.comparator();
        try {
            //根据一个排序好的SortedMap构建红黑树
            buildFromSorted(m.size(), m.entrySet().iterator(), null, null);
        } catch (java.io.IOException cannotHappen) {
        } catch (ClassNotFoundException cannotHappen) {
        }
    }

    public void putAll(Map<? extends K, ? extends V> map) {
        int mapSize = map.size();
        //如果当前TreeMap size为0,目标map size大于0且是SortedMap
        if (size==0 && mapSize!=0 && map instanceof SortedMap) {
            Compar
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值