kri*_*ard 6 java key map treemap comparable
我经历了一些非常怪异的TreeMap行为,我在缩小一个小测试用例时遇到了一些麻烦,所以请耐心等待.
我想从运行时提供的文件中将大量键值对读入Map.我正在使用自定义密钥类.后来,当我把条目撤回时,我发现其中一个或多个丢失了.使用调试器和一些测试用例,我已经确定缺少的条目在读取阶段肯定会消失,但我不确定是什么导致它.
基本上:
Map<MyKey,Double> map = new TreeMap<MyKey,Double>();
map.put(key1,value1);
// ... put another ~500 entries into the map ...
assertTrue(map.containsKey(key1)); // passes
if (!map.containsKey(keyN)) {
map.put(keyN, valueN); // this code executes
}
assertTrue(map.containsKey(key1)); // FAILS
Run Code Online (Sandbox Code Playgroud)
......实质上,向地图添加一个全新的密钥会导致无关的条目失效.
我最初使用TreeMap是因为我希望使用大型数据集,而TreeMap的内存效率更高一些.HashMap将是一个很好的选择,但看到TreeMap以这种方式表现仍然令人震惊 - 任何人都对这里发生的事情有所了解?
sha*_*kan 12
如果比较时,TreeMap认为两个条目相等,则结果为0.因此,如果key1和keyN'与'0'比较,则key1将被putN()覆盖.即使 这样也是如此!key1.equals(keyN).因此,虽然您可能认为这两个键不相等,因此插入一个不应该覆盖另一个,TreeMap如果您的equals和比较函数彼此不一致,则会认为不同.
请注意,这种行为可能会因地图中元素的数量而有所不同,因为它取决于实际比较两个比较方法评估为0的元素.基本上,事情会像你说的那样"诡异".
... map使用compareTo(或compare)方法执行所有键比较,因此从排序映射的角度来看,通过此方法认为相等的两个键相等...
并从可比较的javadocs(感谢@Brian):
强烈建议(尽管不要求)自然排序与equals一致.这是因为没有显式比较器的有序集(和有序映射)在与自然顺序与equals不一致的元素(或键)一起使用时表现得"奇怪".特别是,这样的有序集(或有序映射)违反了集合(或映射)的一般契约,它是根据等于方法定义的.