当按降序排序时,任何机构都可以描述 TreeSet 集合的 high() 方法的这种行为:
法典:
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
现在,尽管集合是按降序排序的,但higher(40)
方法是否应该返回高于 40(当然是 45)的值?
-
set.higher(T)
: 函数返回此集合中严格大于给定元素的最小元素,如果没有这样的元素,则返回null
。 -
set.descendingSet()
:返回此set
中包含的元素的反向顺序view
。
到底发生了什么?
TreeSet
本质上使用 TreeMap
来实现其功能。对descendingSet()
的调用最终调用TreeMap
实例上的 descendingMap()
函数,从以下源代码中可以明显看出:
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