我经历了一些非常诡异的 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
...因此,从本质上讲,向地图添加一个全新的键会导致一个不相关的条目从其中脱落。
- 如果我只添加 key1 和 keyN,key1 会保留在地图中——中间的 500 个条目在某种程度上很重要
- 如果我从 2..(N-1) 中删除一个或两个任意键,则在添加 keyN 时仍会启动 key1
- 如果我从 2..(N-1) 中删除大量键,则在添加 keyN 时 key1 仍然存在,但在添加(比如说)keyQ 时会消失,大约 300 个键进一步向下
- 不幸的是,keyN 踢出 key1 时的地图大小与 keyQ 踢出 key1时的地图大小不同,所以这可能不是一个有限大小的问题
- 如果我改用 HashMap,key1 会保留在地图中
- 自定义键类 MyKey 对 Comparable、equals 和 hashCode 使用相同的逻辑。
我最初使用 TreeMap 是因为我希望使用大型数据集,而 TreeMap 的内存效率更高一些。HashMap 将是一个不错的选择,但是看到 TreeMap 以这种方式运行仍然令人担忧——有人对这里发生的事情有想法吗?