也许我的逻辑停止了一段时间,但我发现这种行为令人困惑。假设我有一个如下的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之间的这种不一致是否正常?请有人请解释一下吗?谢谢。
答案 0 :(得分:1)
我会尝试和#34;总结&#34;以上对某些结构的评论:
TreeMap.lowerEntry(key)
和TreeSet.headSet(key)
具有基本相同的行为,即它们返回低于键的元素。同样适用于TreeMap.higherEntry(key)
和TreeSet.tailSet(key)
。
在它们中的任何一个上使用反向比较器将导致顺序反转,即越高越低越低。当键/元素是数字等时,这似乎是违反直觉的,但这样会颠倒它们的排序顺序。
如果向元素添加一些语义,可能更容易理解:
让我们说我们正在处理一个计算错误发生的票务系统,而某些人则定义了要修复错误的优先级。
现在您想要遍历该错误列表并显示它们,因此您使用TreeMap<Integer, ErrorDescription>
对它们进行排序。
根据键的语义,您可以使用不同的比较器:
最后,你最后评论的引用:
我发现这些功能的文档和/或名称具有误导性。
如果你考虑上面的例子,只是在数字上添加语义会改变&#34; lower&#34;并且&#34;更高&#34;。另外考虑到数字键只是一种键,你也可以使用日期,字符串,枚举或许多其他具有自然顺序的对象(因此实现Comparable
)或需要在逐案(因此使用Comparator
)。
因为文档必须适用于很多不同的情况,所以很难以适合一切的方式编写文档。 &#34;降低&#34;的含义并且&#34;更高&#34;无论如何取决于情况,因此最简单地使用该措辞并将语义的解释留给开发人员。
答案 1 :(得分:0)
你想要的答案可能就在这里:TreeMap(Comparator<? super K> comparator)
构造函数
构造一个新的空树图,根据给定的比较器排序......
<强>参数:强>
comparator
- 将用于订购此地图的比较器。如果为null,则将使用键的自然顺序。
然后,您应该仅针对此comparator
阅读小于和大于。
另外,正如托马斯指出的那样,你可能会对tailSet(key)
的含义感到困惑。从文档中,它应该为您提供大于或等于键的元素。因此,按相反的顺序,您会得到较低的值。