【发布时间】:2015-06-18 08:58:18
【问题描述】:
也许我的逻辑有点停止工作,但我发现这种行为令人困惑。假设我有一个 TreeMap 如下:
TreeMap<Integer, Double> map = new TreeMap<Integer, Double>(Collections.reverseOrder());
map.put(123, 0.5);
map.put(678, 1.0);
map.put(567, 0.1);
int key = 100;
现在,我想使用 map.lowerEntry(key) 并根据 getter 的文档:
返回与严格小于给定键的最大键关联的键值映射,如果没有这样的键,则返回 null。
我希望 null 作为结果,但系统调用 System.out.println("Lower than "+key+ " is "+map.lowerEntry(key)); 会产生 Lower than 100 is 123=0.5。如果我使用 map.higherEntry(key) 记录为
返回与严格大于给定键的最小键关联的键值映射,如果没有这样的键,则返回 null。
然后我得到了想要的结果,但根据文档,它是违反直觉的。我猜想在 TreeMap 上调用 Collections.reverseOrder() 比较器会反转地图内部应用的逻辑?
编辑
使用 TreeSet 在使用 Collections.reverseOrder() 比较器初始化时,我得到一致的行为(关于函数名称):
TreeSet<Integer> set = new TreeSet<Integer>(Collections.reverseOrder());
set.add(123);
set.add(678);
set.add(567);
int key = 200;
System.out.println("Lower than "+key+ " is "+set.tailSet(key));
产生Lower than 200 is [123],这是我所期望的。
TreeMap和TreeSet之间的这种不一致是否正常?有人可以请解释一下吗?谢谢你。
【问题讨论】:
-
当然
Collections.reverseOrder()会颠倒低/高的定义——正如名字所说的那样。 -
嗯,我想应该在文档中指定,或者应该放置一个标志,以防顺序颠倒以保持一致性
-
请记住
reverseOrder()只是Comparator的一个特殊实现,它将反转键的自然顺序(由它们的compareTo()实现定义)。对于多种情况,可能有多种不同的比较器或可比较的实现,您无法在树实现甚至文档中处理所有这些情况。事实上,树形图甚至不知道您传递的比较器反转了顺序。 -
正如我所说,
tailSet()返回比较器定义的“更高”值。因此它类似于higherEntry()(你从低到高或从头到尾迭代)。错误在于这里使用tailSet()而不是headSet()。 -
井头 = 前,尾 = 后。如果您遍历一个有序列表,您通常从定义较低值的前面开始(即,在大多数情况下默认为升序迭代),因此 head->tail = lower->higher。如多次所述:这完全取决于“较低”的定义,在反向比较器的情况下,它与默认值相反。