Should I use put() or putIfAbsent() after using getOrDefault()?

倖福魔咒の 提交于 2019-12-29 06:44:22

问题


Java8 introduced those nice methods getOrDefault() and putIfAbsent(), allowing to write code like:

Map<Foo, List<Bar>> itemsByFoo = ...
List<Bar> bars = itemsByFoo.getOrDefault(key, new ArrayList<>());
bars.add(someNewBar);

Now I am wondering if there are good factual reasons to either do:

itemsByFoo.put(key, bars);

or

itemsByFoo.putIfAbsent(key, bars);

Both would work:

  • option 1 might do a lot of unnecessary "put" calls when adding elements to lists happens often
  • option2 might do a lot of unnecessary "containsKey" calls when adding new entries for new keys is dominant

SO: are the good reasons to go for option 1 or option 2 "always"?


回答1:


getOrDefault is suitable if you want to use a stand-in for an absent value without modifying the map. If you want to add a new value for absent keys, you can do it right in one operation.

List<Bar> bars = itemsByFoo.computeIfAbsent(key, x -> new ArrayList<>());
bars.add(someNewBar);

or even

itemsByFoo.computeIfAbsent(key, x -> new ArrayList<>()).add(someNewBar);

In the best case, when being overridden by the Map implementation, like with HashMap, this will bear a single hash lookup only.

Not that putIfAbsent only bears two lookups when using the default implementation, but, of course, most Map implementations will provide a single lookup implementation for it. Still, the combination of getOrDefault and putIfAbsent would still bear two lookups in the best case, whereas an optimized computeIfAbsent does only one.




回答2:


An important point about computeIfAbsent is that it takes a Function which will only get executed if the Key is absent and we need a default Value.

Whereas getOrDefault requires the default Value itself, already computed. In this case, the default Value we would need is a new ArrayList<Bar>(), which has the side effect of allocating a new object on the heap.

We want to defer doing that until we are sure that the key isn't already in itemsByFoo. Otherwise we would be generating unnecessary garbage for gc to collect.



来源:https://stackoverflow.com/questions/45459014/should-i-use-put-or-putifabsent-after-using-getordefault

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!