zoukankan      html  css  js  c++  java
  • TreeMap和TreeSet在排序时如何比较元素?Collections工具类中的sort()方法如何比较元素?


    原创LiQiyaoo
    展开
    TreeMap和TreeSet都是有序的集合。

    TreeSet要求集合中的元素实现Comparable接口,并实现compareTo方法进行比较,如果compareTo方法实现的不好,可能会导致元素插入失败,因为集合内部也通过compareTo方法来比较元素是否相等(而不是通过equals),即判断一个元素是否可插入。

    TreeMap要求键列的元素实现Comparable接口,与TreeSet对元素的要求一样。

    TreeSet其实内部是通过一个TreeMap来实现的,用了组合的设计模式。

    我们来看下源码

    /**
    * The backing map.
    */
    private transient NavigableMap<E,Object> m;

    // Dummy value to associate with an Object in the backing Map
    private static final Object PRESENT = new Object();

    public TreeSet() {
    this(new TreeMap<E,Object>());
    }
    可以看到,在构造TreeSet时,也构造了一个TreeMap,并且Map中的value不使用。
    我们调用TreeSet的add方法,其实是调用了TreeMap的put方法,我们再看一下源码。

    public boolean add(E e) {
    return m.put(e, PRESENT)==null;
    }
    PRESENT是一个Object对象,没有实际意义,现在我们进入TreeMap看一下put方法的源码。

    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) {
    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);
    }
    else {
    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;
    }
    我们可以看到,方法内是通过元素实现Comparable接口并实现了的compareTo方法来比较两个key是否相等的。并且进行排序。
    第二个问题:

    Collections有两个sort方法,可以仅仅传入一个由实现了Comparable接口元素构成的List对象,当然也可以传入集合中的元素没有实现Comparable的List对象,但是要求传入第二个参数,参数是Comparator接口的子类型(需要重写compare方法实现元素的比较),相当于一个临时定义的排序规则,其实就是通过接口注入比较元素大小的算法,也是对回调模式的应用(Java中对函数式编程的支持)。

    另外一点,

    Collection和Collections有很大区别,Collection是 是一个集合接口。它提供了对集合对象进行基本操作的通用接口方法。Collection接口在Java 类库中有很多具体的实现。Collection接口的意义是为各种具体的集合提供了最大化的统一操作方式。

    而Collections是一个包装类,包装了许多操作集合的静态方法。就相当于一个工具类。
    ————————————————
    版权声明:本文为CSDN博主「LiQiyaoo」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
    原文链接:https://blog.csdn.net/L_BestCoder/article/details/77771412

  • 相关阅读:
    【POJ 3162】 Walking Race (树形DP-求树上最长路径问题,+单调队列)
    【POJ 2152】 Fire (树形DP)
    【POJ 1741】 Tree (树的点分治)
    【POJ 2486】 Apple Tree (树形DP)
    【HDU 3810】 Magina (01背包,优先队列优化,并查集)
    【SGU 390】Tickets (数位DP)
    【SPOJ 2319】 BIGSEQ
    【SPOJ 1182】 SORTBIT
    【HDU 5456】 Matches Puzzle Game (数位DP)
    【HDU 3652】 B-number (数位DP)
  • 原文地址:https://www.cnblogs.com/fangdie/p/12607384.html
Copyright © 2011-2022 走看看