ConcurrentHashMap 中putIfAbsent 和put的区别
putIfAbsent 源代码
public V putIfAbsent(K key, V value) { Segment<K,V> s; if (value == null) throw new NullPointerException(); int hash = hash(key); int j = (hash >>> segmentShift) & segmentMask; if ((s = (Segment<K,V>)UNSAFE.getObject (segments, (j << SSHIFT) + SBASE)) == null) s = ensureSegment(j); return s.put(key, hash, value, true); }
put源代码
public V put(K key, V value) { Segment<K,V> s; if (value == null) throw new NullPointerException(); int hash = hash(key); int j = (hash >>> segmentShift) & segmentMask; if ((s = (Segment<K,V>)UNSAFE.getObject // nonvolatile; recheck (segments, (j << SSHIFT) + SBASE)) == null) // in ensureSegment s = ensureSegment(j); return s.put(key, hash, value, false); }
前面一段都是一样的,都是先计算hash再同步取值,区别在于
s.put(key, hash, value, true); 和
return s.put(key, hash, value, false);
final V put(K key, int hash, V value, boolean onlyIfAbsent) {
for (HashEntry<K,V> e = first;;) { if (e != null) { K k; if ((k = e.key) == key || (e.hash == hash && key.equals(k))) { oldValue = e.value; if (!onlyIfAbsent) { e.value = value; //putIfAbsent下不会进入修改e.value, 在key已经存在的情况下
++modCount; } break; } e = e.next; }
onlyIfAbsent 参数,如果key存在的情况下,在putIfAbsent下不会修改,而put下则会修改成新的值
测试put
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); System.out.println(map.put("1", "1")); System.out.println(map.put("1", "2")); System.out.println(map.get("1"));
结果为:
null
1
2
测试putIfAbsent
ConcurrentHashMap<String, String> map = new ConcurrentHashMap<String, String>(); System.out.println(map.putIfAbsent("1", "1")); System.out.println(map.putIfAbsent("1", "2")); System.out.println(map.get("1"));
结果为:
null
1
1