TreeMap通过Comparator/Comparable实现自定义排序

在向TreeMap中添加对象时,要求对象要么实现了Comparable接口,要么在创建TreeSet时传入了该对象的Comparator比较器,两者选其一即可,否则在添加对象时就会报错。

二者的区别:
Comparable是内比较,如果一个类实现了Comparable接口,那么这个类的实例之间是可以进行比较的。
Comparator是外比较,当一个类没有实现Comparable接口,但是我们仍要进行比较的话,就要通过Comparator比较器来进行比较,除此之外,如果我们对于实现了Comparator接口类本身的比较方法不满意的话,也可以使用外置的Comparator比较器来进行比较,也就是是说,Comparator的优先级是要高于Comparable的。

  • 实现Comparable接口
    TreeMap通过Comparator/Comparable实现自定义排序_第1张图片
  • 传入Comparator比较器
    TreeMap通过Comparator/Comparable实现自定义排序_第2张图片

在TreeSet的add(object)方法是通过调用TreeMap的put(key,value)方法来实现的,key为待添加的对象object,value为一个不可变的常量。
  • 在put方法中首先判断有没有key对象的比较器,如果没有的化就调用key值自身的comparaTo()方法(前提是key对象实现了Comparable接口)
 public V put(K key, V value) {
        Entry<K,V> t = root;
        if (t == null) {
            compare(key, key); // type (and possibly null) check

            root = new Entry<>(key, value, null);
            size = 1;
            modCount++;
            return null;
        }
        int cmp;
        Entry<K,V> parent;
        // split comparator and comparable paths
        Comparator<? super K> cpr = comparator;
        if (cpr != null) { //如果比较器不为空,则通过比较器来比较key的大小
            do {
                parent = t;
                cmp = cpr.compare(key, t.key);
                if (cmp < 0)  // 比较的结果小于0,放在左子节点
                    t = t.left; 
                else if (cmp > 0) // 比较的结果大于0,放在右子节点
                    t = t.right;
                else
                    return t.setValue(value); // 结果等于零,代表key值相等,覆盖value值
            } while (t != null);
        }
        else { // 当没有传入Comparator时,就使用key对象的compareTo方法
            if (key == null)
                throw new NullPointerException();
            @SuppressWarnings("unchecked")
                Comparable<? super K> k = (Comparable<? super K>) key;
            do {
                parent = t;
                cmp = k.compareTo(t.key);
                if (cmp < 0)
                    t = t.left;
                else if (cmp > 0)
                    t = t.right;
                else
                    return t.setValue(value);
            } while (t != null);
        }
        Entry<K,V> e = new Entry<>(key, value, parent);
        if (cmp < 0)
            parent.left = e;
        else
            parent.right = e;
        fixAfterInsertion(e);
        size++;
        modCount++;
        return null;
    }

TreeMap和TreeSet都是通过Comparator中的Compare方法或者Comparable中的compareTo方法或者来判断元素是否相等。

你可能感兴趣的:(数据结构与算法)