TreeMap 底层为数据结构为红黑树,默认为升序排序方式。整个红黑树的结构为:根节点值大于所有左子树节点值,小于所有右子树节点值,由此整个红黑树以深度优先搜索方式遍历一遍为从小到大的升序排列。
如需改为降序排列方式,则应自定义实现 Comparator 接口。
降序排列实现示例:
Map<Integer, Object> map = new TreeMap<Integer, Object>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
map.put(1, 111);
map.put(2, 222);
map.put(3, 333);
map.put(4, 444);
map.put(5, 555);
System.out.println(map);
为何会如此定义 Comparator 实现呢?查看 compare 接口注释如下:
由 compare 接口注释可知,返回负数表示比较的两个对象 o1 小于 o2, 0 表示 o1 等于 o2, 正数表示 o1 大于 o2。
由上图可知,TreeMap put操作时,将put操作的key和此时红黑树的根节点root对应的 t.key 进行比较时:
由此可得,当要降序排列时,则需让更大的值往左子树节点移动,即:
Map<Integer, Object> map = new TreeMap<Integer, Object>(new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return o2 - o1;
}
});
注:o1 表示put进TreeMap的key,o2表示已经存在于TreeMap的key。根据 compare(o1, o2) 的返回值决定o1 的位置。
先放出结论:
1. 当未实现 Comparator 接口时,key 不可以为null,否则抛 NullPointerException 异常;
2. 当实现 Comparator 接口时,若未对 null 情况进行判断,则可能抛 NullPointerException 异常。
1、当未实现 Comparator 接口时,查看 put 源码:
由源码可知,当TreeMap不为空时,key 为 null,则抛 NullPointerException 异常;
当 TreeMap 为空时,put 操作,调用 compare() 方法,源码为:
假如此时 K 类型为Integer,将 key 强制转换时,抛 NullPointerException 异常;
2、当实现 Comparator 接口时, 若未对 null 情况作出判断,则可能抛 NullPointerException 异常:
对对象进行 null 判断的实现示例如下:
public static void main(String[] args) {
Map map1 = new TreeMap(new Comparator() {
@Override
public int compare(Integer o1, Integer o2) {
if (o1 != null && o2 != null) {
return o1 - o2;
}
if (o1 == null && o2 != null) {
return -1;
}
if (o1 != null && o2 == null) {
return 1;
}
return 0;
}
});
map1.put(2, "222");
map1.put(null, "111");
System.out.println(map1);
}