Java8引入了那些不错的方法getOrDefault()
和putIfAbsent()
,允许编写如下代码:
Map<Foo, List<Bar>> itemsByFoo = ...
List<Bar> bars = itemsByFoo.getOrDefault(key, new ArrayList<>());
bars.add(someNewBar);
现在我想知道是否有充分的事实理由:
itemsByFoo.put(key, bars);
或
itemsByFoo.putIfAbsent(key, bars);
两者都可行:
SO:选择1或选项2“总是”的理由是什么?
答案 0 :(得分:20)
getOrDefault
是合适的。如果要为缺席键添加新值,可以在一次操作中正确执行。
List<Bar> bars = itemsByFoo.computeIfAbsent(key, x -> new ArrayList<>());
bars.add(someNewBar);
甚至
itemsByFoo.computeIfAbsent(key, x -> new ArrayList<>()).add(someNewBar);
在最好的情况下,当被Map
实现覆盖时,与HashMap
一样,这将仅包含一个哈希查找。
使用putIfAbsent
实现时,default
只有两次查找,但当然,大多数Map
实现都会为它提供单个查找实现。尽管如此,getOrDefault
和putIfAbsent
的组合仍会在最佳情况下进行两次查找,而优化后的computeIfAbsent
只能进行一次。
答案 1 :(得分:5)
关于computeIfAbsent
的一个要点是它需要Function
,只有在Key
不存在且我们需要默认Value
时才能执行。
getOrDefault
需要默认的Value
本身,已经计算过。在这种情况下,我们需要的默认Value
是new ArrayList<Bar>()
,其副作用是在堆上分配新对象。
我们希望推迟这样做,直到我们确定key
已经在itemsByFoo
中。否则,我们会为gc
生成不必要的垃圾来收集。