阅读一篇有趣的文章,这些人声称这两个函数之间的区别是:
如果指定的Key不是,则两个函数都希望添加元素 已存在于地图中。
putIfAbsent添加具有指定值的元素 computeIfAbsent添加一个元素,其值使用Key计算得出。 http://www.buggybread.com/2014/10/java-8-difference-between-map.html
并且
我们已经看到putIfAbsent消除了必须采取的必要方式 定义if语句,但是如果获取Java文章是什么 真的伤害了我们的表现?
为了优化这一点,我们不希望在我们之前获取文章 我们确实需要它们 - 这意味着我们需要知道密钥是否正确 在取文之前缺席。 http://www.deadcoderising.com/2017-02-14-java-8-declarative-ways-of-modifying-a-map-using-compute-merge-and-replace/
我还没有准备好了解哪些差异可以请你详细说明这两个功能?
答案 0 :(得分:78)
差异#1
computeIfAbsent
采用映射函数,如果缺少键,则调用该函数以获取值。
putIfAbsent
直接获取该值。
如果获取的值很昂贵,那么如果密钥已经存在,则putIfAbsent
会浪费。
常见且价格昂贵的#34;价值是例如new ArrayList<>()
当您创建Map<K, List<V>>
时,如果密钥已存在(然后丢弃新列表),则创建新列表会产生不必要的垃圾。
差异<2
computeIfAbsent
返回&#34;与指定键关联的当前(现有或计算)值,如果计算值为null,则返回null&#34;。
putIfAbsent
返回&#34;与指定键关联的前一个值,如果没有键的映射&#34;则返回null。
因此,如果密钥已经存在,则返回相同的内容,但如果缺少密钥,computeIfAbsent
将返回计算值,而putIfAbsent
将返回null。
差异#3
这两种方法都定义了#34;缺席&#34;密钥缺失或现有值为null,但是:
如果密钥不存在, computeIfAbsent
将不会设置空值。
putIfAbsent
将输入值,即使该值为空。
对computeIfAbsent
,putIfAbsent
和get
来电的未来通话没有任何区别,但它确实对getOrDefault
和{{3}等通话产生了影响}。
答案 1 :(得分:40)
假设您有Map<String,ValueClass>
。
map.putIfAbsent("key", new ValueClass());
无论如何都会创建一个ValueClass
实例,即使“密钥”键已经在Map
中。这只会创建一个不必要的实例。
另一方面
map.computeIfAbsent("key", k -> new ValueClass());
如果“{”}密钥不在ValueClass
中(或映射到Map
值),只会创建null
个实例。
因此computeIfAbsent
效率更高。
putIfAbsent
相当于:
ValueClass value = new ValueClass();
if (map.get("key") == null) {
map.put("key",value);
}
而computeIfAbsent
相当于:
if (map.get("key") == null) {
map.put("key",new ValueClass());
}
这两种方法之间的另一个小差异是computeIfAbsent
不会为缺席密钥设置null
值。 putIfAbsent
会。
答案 2 :(得分:3)
您可以通过仔细查看方法签名来了解其中的差异:
putIfAbsent
获取键和值,如果地图中没有该键的值,则将值放入地图中。computeIfAbsent
获取密钥和Function
。如果地图中没有该键的值,则调用该函数创建该值,然后将其放入地图中。如果您已拥有该值,请使用putIfAbsent
。
如果您还没有该值并且创建该值是一项昂贵的操作(例如,必须在数据库中查找该值),则使用computeIfAbsent
,以便昂贵的操作不会如果地图已经包含指定键的值,则需要执行。
答案 3 :(得分:1)
V putIfAbsent(K key, V value)
- 如果指定的键尚未与值关联(或映射为null),则尝试使用给定的映射函数计算其值,并将其输入此映射,除非为null。
V computeIfAbsent(K key, Function<? super K,? extends V> mappingFunction)
- 如果指定的键尚未与值关联(或映射为null),则尝试使用给定的映射函数计算其值,并将其输入此映射,除非为null。
阅读文档可以给你更明显的答案。 https://docs.oracle.com/javase/8/docs/api/java/util/Map.html
答案 4 :(得分:1)
也许默认的实现可以澄清一点......
default V putIfAbsent(K key, V value)
对于此映射,默认实现等效于:
V v = map.get(key);
if (v == null)
v = map.put(key, value);
return v;
另一方面:
default V computeIfAbsent(K key,
Function<? super K,? extends V> mappingFunction)
相当于:
if (map.get(key) == null) {
V newValue = mappingFunction.apply(key);
if (newValue != null)
map.put(key, newValue);
}
答案 5 :(得分:0)
这个问题已经回答。我花了一些时间来理解(“如果映射已经包含了computeIfAbsent中指定键的值,则不需要执行昂贵的操作”) 我把我的理解这里。希望这对其他人有帮助:
当映射已经包含指定键的值时,putIfAbsent()的行为就像put()一样。 putIfAbsent()仅检查key是否为null。 如果它不为null,则返回该值,然后map再次获取该值。
但是,在computeIfAbsent()中,对键和值都没有null检查。在对值进行null检查期间,如果不为null,则来自地图对象的现有值 被分配给newValue并返回。这就是为什么在重新使用map中的现有值时无需再次获取值的原因。
请参考以下程序以供参考:
public class MapTest1 {
public static final String AJAY_DEVGAN = "Ajay Devgn";
public static final String AUTOBIOGRAPHY = "Autobiography";
public static void main(String[] args) {
MapTest1 mt = new MapTest1();
mt.testPutCompute();
}
private void testPutCompute() {
Map<String, List<String>> movies = getMovieObject();
System.out.println("\nCalling putIfAbsent method.....");
//System.out.println(movies.get(AJAY_DEVGAN));
//movies.put(AJAY_DEVGAN, getAjayDevgnMovies());
movies.putIfAbsent(AJAY_DEVGAN, getAjayDevgnMovies());
System.out.println("\nCalling computeIfAbsent method......");
//System.out.println(movies.get(AUTOBIOGRAPHY));
movies.computeIfAbsent(AUTOBIOGRAPHY, t -> getAutobiographyMovies());
}
private Map<String, List<String>> getMovieObject() {
Map<String, List<String>> movies = new HashMap<>();
movies.put(AJAY_DEVGAN, getAjayDevgnMovies());
movies.put(AUTOBIOGRAPHY, getAutobiographyMovies());
System.out.println(movies);
return movies;
}
private List<String> getAutobiographyMovies() {
System.out.println("Getting autobiography movies");
List<String> list = new ArrayList<>();
list.add("M.S. Dhoni - The Untold Story");
list.add("Sachin: A Billion Dreams");
return list;
}
private List<String> getAjayDevgnMovies() {
System.out.println("Getting Ajay Devgn Movies");
List<String> ajayDevgnMovies = new ArrayList<>();
ajayDevgnMovies.add("Jigar");
ajayDevgnMovies.add("Pyar To Hona Hi Tha");
return ajayDevgnMovies;
}
}
请从接口Map.class引用putIfAbsent()和computeIfAbsent()的以下代码
public interface Map<K,V> {
.....
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
default V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
V v;
if ((v = get(key)) == null) {
V newValue;
if ((newValue = mappingFunction.apply(key)) != null) {
put(key, newValue);
return newValue;
}
}
return v;
}
.........
}
答案 6 :(得分:-1)
Take this simple Example for putIfAbsent():
Map myMap = new HashMap();
myMap.put(1,"ABC");
myMap.put(2,"XYZ");
myMap.put(3,"GHI");
//Output of map till this point is : 1-> "ABC", 2-> "XYZ", 3-> "GHI"
myMap.putIfAbsent(3,"cx");
//Output of map till this point is : 1-> "ABC", 2-> "XYZ", 3-> "GHI"
cx will be value of 3 if there is no Value of 3 in the map already.