我有这个地图定义:
TreeMap <String, Set<Integer>>
它可能包含数百万个条目,而且我还需要一个“自然顺序”(这就是我选择 TreeMap 的原因,尽管如果需要我可以编写一个 Comparator)。
因此,为了向地图添加元素,我必须做的是:
- 检查密钥是否已经存在。
- 如果没有,请创建一个新 Set 并添加该值。
- 如果存在,我必须将值添加到 Set
我有这个工作正常的实现:
private void addToMap (String key, Integer value){
Set<Integer> vs = dataMap.get(key);
if (vs == null){
vs = new TreeSet<Integer>();
dataMap.put(key,vs);
}
vs.add(value);
}
但是我想避免搜索键,然后如果它不存在则放置元素(它将在巨大的地图上执行新的搜索)。
我想我可以使用ConcurrentHashMap.putIfAbsent
方法,但是:
- 我不会有键的自然排序(我需要对数百万个键执行排序)
- 由于 ConcurrentHashMap 上的同步,我可能会有(我不知道)额外的开销,在我的情况下,我的进程是单线程的,它可能会影响性能。
阅读这篇文章:Java map.get(key) - 如果 key 不存在,自动执行 put(key) 并返回?
有一个关于番石榴的答案,MapMaker.makeComputingMap
但看起来该方法不再存在。
在这种情况下,性能至关重要(一如既往:D),所以请告诉我您的建议。
提前致谢。
注意: 非常感谢您在几分钟内提供了如此多的帮助答案。(我不知道选哪个最好)。
我将对建议(TreeMultiMap、ConcurrentSkipListMap、TreeSet + HashMap)进行一些性能测试并更新结果。然后我会选择性能最好的一个,因为我想选择所有三个但我不能。
笔记2
因此,我对 150 万个条目进行了一些性能测试,结果如下:
ConcurrentSkipListMap,它没有像我预期的那样工作,因为它用我提供的新空集替换了现有值。我认为只有在密钥不存在时才设置值,所以我不能使用这个。(我的错)。
TreeSet + HashMap,工作正常,但不能提供最佳性能。它比单独的 TreeMap 或 TreeMultiMap 慢 1.5 倍。
TreeMultiMap 提供了最好的性能,但它与单独的 TreeMap 几乎相同。我会检查这个作为答案。
再次感谢您的贡献和帮助。