Java TreeMap的使用

TreeMap 按照 Key 的排序结果来组织内部结构的Map类集合,它改变了Map类散乱无序的形象。虽然TreeMap没有ConcurrentHashMap 和 HashMap 普及,但是在Key有排序的要求的场景下,使用 TreeMap 可以事半功倍。在集合框架如中,他们都继承AbstractMap 抽象类,TreeMap 与 HashMap 、ConcurrentHashMap 的类图关系如下:

在这里插入图片描述
在这里插入图片描述

  • TreeMap 继承于AbstractMap,所以它是一个Map,即一个key-value集合。
  • TreeMap 实现了 SortedMap 接口,表示它的Key是有序的。支持获取头尾 Key-Value 元素,或者根据Key指定范围获取子集合等。插入的Key 必须实现Comparable 或者 提供额外的比较器 Comparator,所以Key不允许为null, 但是Value可以
  • TreeMap 实现 NavigableMap 接口继承了 SortedMap 接口,根据指定的搜索条件返回最匹配的Key-Value元素。不同于HashMap,TreeMap 并非一定要覆写hashCode 和 equals 方法来达到Key去重的目的。
  • TreeMap 实现了Cloneable接口,意味着它能被克隆。
  • TreeMap 实现了java.io.Serializable接口,意味着它支持序列化。
public class TreeMapTest {
    public static void main(String[] args) {
        //如果把此处的TreeMap 换成 HashMap ,则 size = 1
        TreeMap treeMap = new TreeMap();
        treeMap.put(new Key(),"value  one");
        treeMap.put(new Key(),"value  two");
        // TreeMap ,size = 2 , 因为Key 去重规是根据排序结果
        System.out.println(treeMap.size());
    }

    static class Key implements  Comparable<Key>{
        @Override
        public int compareTo(Key o) {
            //返回负数的常数,表示此对象永远小于输入的other对象,此处决定TreeMap的size=2
            return -1;
        }
        @Override
        public int hashCode() {
            return 1;
        }
        @Override
        public boolean equals(Object obj) {
            return true;
        }
    }
}

上面的例子,如果把TreeMap 换成 HashMap ,size的结果则从2变成1。

注意 HashMap 是使用 hashCode 和 equals 实现去重的。

而TreeMap 则依靠Comparable 或 Comparator 来实现Key的 去重,

TreeMap 有两种排序:

  1. 自然排序: TreeMap 的所有Key必须实现 Comparable 接口,而且所有的key应该是同一个类的对象,否则将会抛出 ClassCastException 异常。
  2. 定制排序: 创建TreeMap 时,传入一个Comparator对象,该对象负责对TreeMap中的所有key进行排序。采用定制排序时不要求Map的key实现 Comparable接口。

如果没有覆盖正确的方法,那么TreeMap 的最大特性将无法发挥出来,甚至在运行时出现异常。如果要用TreeMap对Key进行排序,调用如下方法:

  final int compare(Object k1, Object k2) {
        return comparator==null ? ((Comparable<? super K>)k1).compareTo((K)k2)
            : comparator.compare((K)k1, (K)k2);
    }

如果 comparator 不为null, 优先使用 comparator 的compare方法;
如果为null, 则使用Key实现的自然排序Comparable接口的 compareTo 方法。如果两者都无法满足,则抛出异常;

Exception in thread "main" java.lang.ClassCastException: com.yaspeed2.TreeMapTest$Key cannot be cast to java.lang.Comparable
	at java.util.TreeMap.compare(TreeMap.java:1294)
	at java.util.TreeMap.put(TreeMap.java:538)
	at com.yaspeed2.TreeMapTest.main(TreeMapTest.java:9)

TreeMap 中判断两个key 相等的标准是: 两个key通过compareTo() 方法返回0,TreeMap 即认为这两个key是相等的。

如果使用自定义类作为TreeMap的key, 且让TreeMap 良好的工作,则重写该类的equals() 方法和compareTo() 方法时应保持一致的返回结果: 两个key 通过equals() 方法比较返回true时,他们通过compareTo() 返回比较应该返回0。如果equals()方法与compareTo()方法的返回结果不一致,TreeMap与Map接口的规则就会冲突。

在这里插入图片描述

  • 0
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

半夏_2021

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值