任何人都可以描述TreeSet集合的Higher()方法的这种行为,当它以降序排序时:

码:

NavigableSet<Integer> set = new TreeSet<>();

set.add(10);
set.add(22);
set.add(34);
set.add(40);
set.add(45);
set.add(56);
set.add(77);
set.add(79);
set.add(84);
set.add(99);

set = set.descendingSet();

System.out.printf("%n Higher than 40 : %s", set.higher(40));


返回以下结果。

Higher than 40 : 34


现在,尽管collection按降序排序,但higher(40)方法是否应该返回大于40的值(当然是45)?

最佳答案

set.higher(T):函数返回该集合中的最小元素,该元素严格大于给定元素;如果没有此类元素,则返回null
set.descendingSet():返回此view中包含的元素的逆序set


到底发生了什么?

TreeSet本质上使用TreeMap来实现其功能。对descendingSet()的调用最终会在descendingMap()实例上调用TreeMap函数,如以下源代码所示:

public NavigableSet<E> descendingSet() {
        return new TreeSet<>(m.descendingMap());
    }


每个TreeMap通常维护两个视图:


普通排序视图:使用通用比较器对元素进行排序
后代地图视图:使用比较器,该比较器强加了升序比较器的顺序。它使用Collections.reverseOrder(m.comparator())返回此降序比较器。


我之所以称呼这些view是因为TreeMap实际上并没有使用其条目(键,值)创建另一个后代Map,而是维护了两个比较器,彼此施加相反的顺序。调用descendantMap()时,将首次创建后代视图。随后调用此函数将返回相同的后代Map视图。

注意:set.descendingSet().descendingSet()返回的set视图基本上等同于set。因为第一次调用的结果比较器再次被descendingSet()的第二次调用反转了(实际上是在内部执行map.descendingMap())。

继续您的示例:

System.out.printf("%n Higher than 40 : %s", set.higher(40)); // prints 45
set = set.descendingSet(); // create a reverse ordering
                           //comparator as described above
System.out.printf("%n Higher than 40 : %s", set.higher(40)); // prints 34
set = set.descendingSet(); // again trying to get descending set!
System.out.printf("%n Higher than 40 : %s", set.higher(40))  // prints 45

08-17 23:23