1. SortedMap的实现类——TreeMap:
1) 就像SortedSet的实现类TreeSet一样,TreeMap的数据结构完全和SortedSet一样,用红黑树实现;
2) TreeMap和TreeSet比较之后的特点就是:
i. 是根据Entry的key的大小进行排序(对Entry进行排序),即用key来代表Entry的大小;
ii. 自然排序需要实现key的compareTo,定制排序(构造器传一个Comparable闭包)也是根据key进行比较的:TreeMap(Comparator<? super K> comparator);
iii. 实现时也需要保证key的equals和compare的结果一致,如果不一致则存储Entry时会导致和Map的规则冲突;
2. TreeMap的对象方法:基本和TreeSet的形式一样的,只不过方法名的后缀是Key、Entry、Map
1) first/last系列:分别提供了检索entry和key的方法
i. Map.Entry<K,V> firstEntry | lastEntry(); // 获取第一个/最后一个entry
ii. K firstKey | lastKey(); // 获取第一个/最后一个entry的键
2) lower/higher系列:也是分别提供了检索entry和key的方法
i. Map.Entry<K,V> lowerEntry | higherEntry(K key); // 获取比指定key所对应的entry小/大一位的entry
ii. K lowerKey | higherKey(K key); // 获取比指定key大/小一位的key
3) head/tail/sub系列(获取子区间):返回的都是SortedMap(即纯子集)
i. SortedMap<K,V> headMap(K toKey); // 所有小于toKey(不包括toKey)的子集
ii. SortedMap<K,V> tailMap(K fromKey); // 所有大于等于fromKey的子集
iii. SortedMap<K,V> subMap(K fromKey, K toKey); // 返回[fromKey, toKey)区间的子集
4) 示例:
class R implements Comparable {
int val;
public R(int val) {
this.val = val;
}
@Override
public String toString() {
return "R[val:" + val + "]";
}
@Override
public boolean equals(Object obj) { // equals的标准写法
if (this == obj) { // 先比较地址
return true;
}
if (obj != null && obj.getClass() == R.class) { // 再比较类型(前提是obj不能为空)
R r = (R)obj; // 先把类型调整一致(当然可以直接return this.val == ((R)obj).val
// 但如果在return之前还要用obj进行一些其它复杂操作那用临时的类型转换太麻烦了
// 因此先协调类型才是最标准最合理的做法
return this.val == r.val;
}
return false; // 地址不同 || obj为空 || 类型不一致,那肯定不一样了!
}
@Override
public int compareTo(Object o) { // compareTo的标准写法
if (this == o) { // 第一步和equals一样,还是先比较地址,这是最基本也是最容易想到的
return 0;
}
if (o == null) { // 由于compareTo比较的是大小,而null是没法比较大小的,因此null就得抛异常
// 这里只是个演示,就不实现这一块了
// 抛出异常
}
R r = (R)o; // 不判断类型是否一致,不一致直接抛出异常!就是要暴露异常方便调试(集合中元素都应该保证类型相同)
return this.val - r.val; // 正常的操作和返回
}
}
public class Test {
public static void main(String[] args) {
TreeMap map = new TreeMap();
map.put(new R(9), "aaa");
map.put(new R(5), "bbb");
map.put(new R(-3), "ccc");
System.out.println(map); // key: -3, 5, 9
System.out.println(map.firstEntry()); // key: -3
System.out.println(map.lastKey()); // key: 9
System.out.println(map.higherKey(new R(2))); // key: 5
System.out.println(map.lowerEntry(new R(1))); // key: -3
System.out.println(map.subMap(new R(-1), new R(10))); // key: 5, 9
}
}