TreeMap本身是默认带有升序排序的策略的,如果要修改其排序规则,有2种方式。
1、实体元素实现Comparable接口,重写compareTo方法。
2、实现Cpmparator 重写compare方法。
以第二种方法为例,该方法会返回一个数字,根据该数字来判定如何进行排序。
Map<Integer,List<String>> map = new <Integer, List<String>>(
new Comparator<Integer>() {
public int compare(Integer obj1, Integer obj2) {
if(obj1 > obj2){
return 正数 or 负数 or 0
}
}
});
返回数值的排序规则为:
返回正数 :升序排序。
返回负数: 降序排序。
返回 0 : 抛弃数据,返回0是指key相同,TreeMap继承自AbstractMap其定义是不允许出现key相同的情况。
那么它是如何通过返回值完成排序的呢?
我们先看下TreeMap的数据结构:
--TreeMap的每个存储元素为Entry类
static final class Entry<K,V> implements Map.Entry<K,V> {
K key;
V value;
Entry<K,V> left;
Entry<K,V> right;
Entry<K,V> parent;
boolean color = BLACK;
。。。
}
TreeMap的数据结构是红黑树结构,从其中的成员变量命名就可以看出。
看完结构后再打开关键方法put()看下是如何判断的:
public V put(K key, V value) {
。。。
//如果自定义排序器不为空则进入
if (cpr != null) {
do {
parent = t;
//自定义排序规则的返回
cmp = cpr.compare(key, t.key);
if (cmp < 0)
t = t.left;
else if (cmp > 0)
t = t.right;
else
return t.setValue(value);
} while (t != null);
}
。。。
}
在TreeMap进行put时,如果自定义比较器存在,则会根据自定义的compare返回来判断,如果小于0(-1)则放在节点的左边,如果大于0(1)则放在节点的右边。
看到这里存的部分基本关于排序的都看了,在取的时候,也用到了排序器
final Entry<K,V> getEntryUsingComparator(Object key) {
@SuppressWarnings("unchecked")
K k = (K) key;
Comparator<? super K> cpr = comparator;
if (cpr != null) {
Entry<K,V> p = root;
while (p != null) {
//排序器
int cmp = cpr.compare(k, p.key);
if (cmp < 0)
p = p.left;
else if (cmp > 0)
p = p.right;
else
return p;
}
}
return null;
}