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