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;
- }