提交 ad59a26e 编写于 作者: C chegar

Merge

......@@ -28,6 +28,9 @@ import java.io.Serializable;
import java.io.ObjectOutputStream;
import java.io.IOException;
import java.lang.reflect.Array;
import java.util.function.BiConsumer;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* This class consists exclusively of static methods that operate on or return
......@@ -264,8 +267,7 @@ public class Collections {
}
private static <T>
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key)
{
int indexedBinarySearch(List<? extends Comparable<? super T>> list, T key) {
int low = 0;
int high = list.size()-1;
......@@ -441,21 +443,21 @@ public class Collections {
/**
* Randomly permutes the specified list using a default source of
* randomness. All permutations occur with approximately equal
* likelihood.<p>
* likelihood.
*
* The hedge "approximately" is used in the foregoing description because
* <p>The hedge "approximately" is used in the foregoing description because
* default source of randomness is only approximately an unbiased source
* of independently chosen bits. If it were a perfect source of randomly
* chosen bits, then the algorithm would choose permutations with perfect
* uniformity.<p>
* uniformity.
*
* This implementation traverses the list backwards, from the last element
* up to the second, repeatedly swapping a randomly selected element into
* the "current position". Elements are randomly selected from the
* <p>This implementation traverses the list backwards, from the last
* element up to the second, repeatedly swapping a randomly selected element
* into the "current position". Elements are randomly selected from the
* portion of the list that runs from the first element to the current
* position, inclusive.<p>
* position, inclusive.
*
* This method runs in linear time. If the specified list does not
* <p>This method runs in linear time. If the specified list does not
* implement the {@link RandomAccess} interface and is large, this
* implementation dumps the specified list into an array before shuffling
* it, and dumps the shuffled array back into the list. This avoids the
......@@ -469,9 +471,10 @@ public class Collections {
public static void shuffle(List<?> list) {
Random rnd = r;
if (rnd == null)
r = rnd = new Random();
r = rnd = new Random(); // harmless race.
shuffle(list, rnd);
}
private static Random r;
/**
......@@ -1391,6 +1394,67 @@ public class Collections {
public int hashCode() {return m.hashCode();}
public String toString() {return m.toString();}
// Override default methods in Map
@Override
@SuppressWarnings("unchecked")
public V getOrDefault(Object k, V defaultValue) {
// Safe cast as we don't change the value
return ((Map<K, V>)m).getOrDefault(k, defaultValue);
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
m.forEach(action);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
/**
* We need this class in addition to UnmodifiableSet as
* Map.Entries themselves permit modification of the backing Map
......@@ -1590,9 +1654,9 @@ public class Collections {
* </pre>
* Failure to follow this advice may result in non-deterministic behavior.
*
* <p>The returned collection does <i>not</i> pass the <tt>hashCode</tt>
* and <tt>equals</tt> operations through to the backing collection, but
* relies on <tt>Object</tt>'s equals and hashCode methods. This is
* <p>The returned collection does <i>not</i> pass the {@code hashCode}
* and {@code equals} operations through to the backing collection, but
* relies on {@code Object}'s equals and hashCode methods. This is
* necessary to preserve the contracts of these operations in the case
* that the backing collection is a set or a list.<p>
*
......@@ -2107,6 +2171,57 @@ public class Collections {
public String toString() {
synchronized (mutex) {return m.toString();}
}
// Override default methods in Map
@Override
public V getOrDefault(Object k, V defaultValue) {
synchronized (mutex) {return m.getOrDefault(k, defaultValue);}
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
synchronized (mutex) {m.forEach(action);}
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
synchronized (mutex) {m.replaceAll(function);}
}
@Override
public V putIfAbsent(K key, V value) {
synchronized (mutex) {return m.putIfAbsent(key, value);}
}
@Override
public boolean remove(Object key, Object value) {
synchronized (mutex) {return m.remove(key, value);}
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
synchronized (mutex) {return m.replace(key, oldValue, newValue);}
}
@Override
public V replace(K key, V value) {
synchronized (mutex) {return m.replace(key, value);}
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
synchronized (mutex) {return m.computeIfAbsent(key, mappingFunction);}
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.computeIfPresent(key, remappingFunction);}
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.compute(key, remappingFunction);}
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
synchronized (mutex) {return m.merge(key, value, remappingFunction);}
}
private void writeObject(ObjectOutputStream s) throws IOException {
synchronized (mutex) {s.defaultWriteObject();}
}
......@@ -2326,6 +2441,8 @@ public class Collections {
}
public Iterator<E> iterator() {
// JDK-6363904 - unwrapped iterator could be typecast to
// ListIterator with unsafe set()
final Iterator<E> it = c.iterator();
return new Iterator<E>() {
public boolean hasNext() { return it.hasNext(); }
......@@ -2652,7 +2769,7 @@ public class Collections {
public List<E> subList(int fromIndex, int toIndex) {
return new CheckedRandomAccessList<>(
list.subList(fromIndex, toIndex), type);
list.subList(fromIndex, toIndex), type);
}
}
......@@ -2717,14 +2834,24 @@ public class Collections {
throw new ClassCastException(badValueMsg(value));
}
private BiFunction<? super K, ? super V, ? extends V> typeCheck(
BiFunction<? super K, ? super V, ? extends V> func) {
Objects.requireNonNull(func);
return (k, v) -> {
V newValue = func.apply(k, v);
typeCheck(k, newValue);
return newValue;
};
}
private String badKeyMsg(Object key) {
return "Attempt to insert " + key.getClass() +
" key into map with key type " + keyType;
" key into map with key type " + keyType;
}
private String badValueMsg(Object value) {
return "Attempt to insert " + value.getClass() +
" value into map with value type " + valueType;
" value into map with value type " + valueType;
}
CheckedMap(Map<K, V> m, Class<K> keyType, Class<V> valueType) {
......@@ -2768,7 +2895,7 @@ public class Collections {
Object v = e.getValue();
typeCheck(k, v);
checked.add(
new AbstractMap.SimpleImmutableEntry<>((K) k, (V) v));
new AbstractMap.SimpleImmutableEntry<>((K)k, (V)v));
}
for (Map.Entry<K,V> e : checked)
m.put(e.getKey(), e.getValue());
......@@ -2782,6 +2909,74 @@ public class Collections {
return entrySet;
}
// Override default methods in Map
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
m.forEach(action);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
m.replaceAll(typeCheck(function));
}
@Override
public V putIfAbsent(K key, V value) {
typeCheck(key, value);
return m.putIfAbsent(key, value);
}
@Override
public boolean remove(Object key, Object value) {
return m.remove(key, value);
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
typeCheck(key, newValue);
return m.replace(key, oldValue, newValue);
}
@Override
public V replace(K key, V value) {
typeCheck(key, value);
return m.replace(key, value);
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
return m.computeIfAbsent(key, k -> {
V value = mappingFunction.apply(k);
typeCheck(k, value);
return value;
});
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
return m.computeIfPresent(key, typeCheck(remappingFunction));
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
return m.compute(key, typeCheck(remappingFunction));
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
return m.merge(key, value, (v1, v2) -> {
V newValue = remappingFunction.apply(v1, v2);
typeCheck(null, newValue);
return newValue;
});
}
/**
* We need this class in addition to CheckedSet as Map.Entry permits
* modification of the backing Map via the setValue operation. This
......@@ -3456,6 +3651,67 @@ public class Collections {
public int hashCode() {return 0;}
// Override default methods in Map
@Override
@SuppressWarnings("unchecked")
public V getOrDefault(Object k, V defaultValue) {
return defaultValue;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
Objects.requireNonNull(function);
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
// Preserves singleton property
private Object readResolve() {
return EMPTY_MAP;
......@@ -3619,6 +3875,65 @@ public class Collections {
return values;
}
// Override default methods in Map
@Override
public V getOrDefault(Object key, V defaultValue) {
return eq(key, k) ? v : defaultValue;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
action.accept(k, v);
}
@Override
public void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
throw new UnsupportedOperationException();
}
@Override
public V putIfAbsent(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public boolean remove(Object key, Object value) {
throw new UnsupportedOperationException();
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
throw new UnsupportedOperationException();
}
@Override
public V replace(K key, V value) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfAbsent(K key,
Function<? super K, ? extends V> mappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V compute(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
@Override
public V merge(K key, V value,
BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
throw new UnsupportedOperationException();
}
}
// Miscellaneous
......
/*
* Copyright (c) 1997, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -24,7 +24,11 @@
*/
package java.util;
import java.io.*;
import java.util.function.Consumer;
import java.util.function.BiFunction;
import java.util.function.Function;
/**
* Hash table based implementation of the <tt>Map</tt> interface. This
......@@ -376,6 +380,13 @@ public class HashMap<K,V>
return null == entry ? null : entry.getValue();
}
@Override
public V getOrDefault(Object key, V defaultValue) {
Entry<K,V> entry = getEntry(key);
return (entry == null) ? defaultValue : entry.getValue();
}
/**
* Returns <tt>true</tt> if this map contains a mapping for the
* specified key.
......@@ -603,6 +614,261 @@ public class HashMap<K,V>
return (e == null ? null : e.value);
}
// optimized implementations of default methods in Map
@Override
public V putIfAbsent(K key, V value) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for(; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
if(e.value != null) {
return e.value;
}
e.value = value;
modCount++;
e.recordAccess(this);
return null;
}
}
modCount++;
addEntry(hash, key, value, i);
return null;
}
@Override
public boolean remove(Object key, Object value) {
if (isEmpty()) {
return false;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
if (!Objects.equals(e.value, value)) {
return false;
}
modCount++;
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
return true;
}
prev = e;
e = next;
}
return false;
}
@Override
public boolean replace(K key, V oldValue, V newValue) {
if (isEmpty()) {
return false;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key) && Objects.equals(e.value, oldValue)) {
e.value = newValue;
e.recordAccess(this);
return true;
}
}
return false;
}
@Override
public V replace(K key, V value) {
if (isEmpty()) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
return null;
}
@Override
public V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)table[i];
for (; e != null; e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
return oldValue == null ? (e.value = mappingFunction.apply(key)) : oldValue;
}
}
V newValue = mappingFunction.apply(key);
if (newValue != null) {
modCount++;
addEntry(hash, key, newValue, i);
}
return newValue;
}
@Override
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (isEmpty()) {
return null;
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
if (oldValue == null)
break;
V newValue = remappingFunction.apply(key, oldValue);
modCount++;
if (newValue == null) {
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
} else {
e.value = newValue;
e.recordAccess(this);
}
return newValue;
}
prev = e;
e = next;
}
return null;
}
@Override
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != oldValue) {
modCount++;
if (newValue == null) {
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
} else {
e.value = newValue;
e.recordAccess(this);
}
}
return newValue;
}
prev = e;
e = next;
}
V newValue = remappingFunction.apply(key, null);
if (newValue != null) {
modCount++;
addEntry(hash, key, newValue, i);
}
return newValue;
}
@Override
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
if (table == EMPTY_TABLE) {
inflateTable(threshold);
}
int hash = (key == null) ? 0 : hash(key);
int i = indexFor(hash, table.length);
@SuppressWarnings("unchecked")
Entry<K,V> prev = (Entry<K,V>)table[i];
Entry<K,V> e = prev;
while (e != null) {
Entry<K,V> next = e.next;
if (e.hash == hash && Objects.equals(e.key, key)) {
V oldValue = e.value;
V newValue = remappingFunction.apply(oldValue, value);
modCount++;
if (newValue == null) {
size--;
if (prev == e)
table[i] = next;
else
prev.next = next;
e.recordRemoval(this);
} else {
e.value = newValue;
e.recordAccess(this);
}
return newValue;
}
prev = e;
e = next;
}
if (value != null) {
modCount++;
addEntry(hash, key, value, i);
}
return value;
}
// end of optimized implementations of default methods in Map
/**
* Removes and returns the entry associated with the specified key
* in the HashMap. Returns null if the HashMap contains no mapping
......@@ -697,8 +963,8 @@ public class HashMap<K,V>
return containsNullValue();
Entry<?,?>[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next)
for (int i = 0; i < tab.length; i++)
for (Entry<?,?> e = tab[i]; e != null; e = e.next)
if (value.equals(e.value))
return true;
return false;
......@@ -709,8 +975,8 @@ public class HashMap<K,V>
*/
private boolean containsNullValue() {
Entry<?,?>[] tab = table;
for (int i = 0; i < tab.length ; i++)
for (Entry<?,?> e = tab[i] ; e != null ; e = e.next)
for (int i = 0; i < tab.length; i++)
for (Entry<?,?> e = tab[i]; e != null; e = e.next)
if (e.value == null)
return true;
return false;
......
/*
* Copyright (c) 1994, 2012, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1994, 2013, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
......@@ -24,7 +24,11 @@
*/
package java.util;
import java.io.*;
import java.util.function.BiConsumer;
import java.util.function.Function;
import java.util.function.BiFunction;
/**
* This class implements a hash table, which maps keys to values. Any
......@@ -455,6 +459,26 @@ public class Hashtable<K,V>
}
}
private void addEntry(int hash, K key, V value, int index) {
modCount++;
Entry<?,?> tab[] = table;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>) tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
}
/**
* Maps the specified <code>key</code> to the specified
* <code>value</code> in this hashtable. Neither the key nor the
......@@ -492,21 +516,7 @@ public class Hashtable<K,V>
}
}
modCount++;
if (count >= threshold) {
// Rehash the table if the threshold is exceeded
rehash();
tab = table;
hash = hash(key);
index = (hash & 0x7FFFFFFF) % tab.length;
}
// Creates the new entry.
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
tab[index] = new Entry<>(hash, key, value, e);
count++;
addEntry(hash, key, value, index);
return null;
}
......@@ -892,6 +902,239 @@ public class Hashtable<K,V>
return h;
}
@Override
public synchronized V getOrDefault(Object key, V defaultValue) {
V result = get(key);
return (null == result) ? defaultValue : result;
}
@Override
public synchronized void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action); // explicit check required in case
// table is empty.
Entry<?,?>[] tab = table;
for (Entry<?,?> entry : tab) {
while (entry != null) {
action.accept((K)entry.key, (V)entry.value);
entry = entry.next;
}
}
}
@Override
public synchronized void replaceAll(
BiFunction<? super K, ? super V, ? extends V> function) {
Map.super.replaceAll(function);
}
@Override
public synchronized V putIfAbsent(K key, V value) {
Objects.requireNonNull(value);
// Makes sure the key is not already in the hashtable.
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> entry = (Entry<K,V>)tab[index];
for (; entry != null; entry = entry.next) {
if ((entry.hash == hash) && entry.key.equals(key)) {
V old = entry.value;
if (old == null) {
entry.value = value;
}
return old;
}
}
addEntry(hash, key, value, index);
return null;
}
@Override
public synchronized boolean remove(Object key, Object value) {
Objects.requireNonNull(value);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if ((e.hash == hash) && e.key.equals(key) && e.value.equals(value)) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
e.value = null;
return true;
}
}
return false;
}
@Override
public synchronized boolean replace(K key, V oldValue, V newValue) {
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (; e != null; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
if (e.value.equals(oldValue)) {
e.value = newValue;
return true;
} else {
return false;
}
}
}
return false;
}
@Override
public synchronized V replace(K key, V value) {
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (; e != null; e = e.next) {
if ((e.hash == hash) && e.key.equals(key)) {
V oldValue = e.value;
e.value = value;
return oldValue;
}
}
return null;
}
@Override
public synchronized V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction) {
Objects.requireNonNull(mappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (; e != null; e = e.next) {
if (e.hash == hash && e.key.equals(key)) {
// Hashtable not accept null value
return e.value;
}
}
V newValue = mappingFunction.apply(key);
if (newValue != null) {
addEntry(hash, key, newValue, index);
}
return newValue;
}
@Override
public V computeIfPresent(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash == hash && e.key.equals(key)) {
V newValue = remappingFunction.apply(key, e.value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
return null;
}
@Override
public V compute(K key, BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash == hash && Objects.equals(e.key, key)) {
V newValue = remappingFunction.apply(key, e.value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
V newValue = remappingFunction.apply(key, null);
if (newValue != null) {
addEntry(hash, key, newValue, index);
}
return newValue;
}
@Override
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
Entry<?,?> tab[] = table;
int hash = hash(key);
int index = (hash & 0x7FFFFFFF) % tab.length;
@SuppressWarnings("unchecked")
Entry<K,V> e = (Entry<K,V>)tab[index];
for (Entry<K,V> prev = null; e != null; prev = e, e = e.next) {
if (e.hash == hash && e.key.equals(key)) {
V newValue = remappingFunction.apply(e.value, value);
if (newValue == null) {
modCount++;
if (prev != null) {
prev.next = e.next;
} else {
tab[index] = e.next;
}
count--;
} else {
e.value = newValue;
}
return newValue;
}
}
if (value != null) {
addEntry(hash, key, value, index);
}
return value;
}
/**
* Save the state of the Hashtable to a stream (i.e., serialize it).
*
......
......@@ -38,7 +38,7 @@ import java.util.Map;
/**
* A {@link java.util.Map} providing additional atomic
* <tt>putIfAbsent</tt>, <tt>remove</tt>, and <tt>replace</tt> methods.
* {@code putIfAbsent}, {@code remove}, and {@code replace} methods.
*
* <p>Memory consistency effects: As with other concurrent
* collections, actions in a thread prior to placing an object into a
......@@ -57,6 +57,21 @@ import java.util.Map;
* @param <V> the type of mapped values
*/
public interface ConcurrentMap<K, V> extends Map<K, V> {
/**
* {@inheritDoc}
*
* @implNote This implementation assumes that the ConcurrentMap cannot
* contain null values and get() returning null unambiguously means the key
* is absent. Implementations which support null values must override this
* default implementation.
*/
@Override
default V getOrDefault(Object key, V defaultValue) {
V v;
return ((v = get(key)) != null) ? v : defaultValue;
}
/**
* If the specified key is not already associated
* with a value, associate it with the given value.
......@@ -91,7 +106,7 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* Removes the entry for a key only if currently mapped to a given value.
* This is equivalent to
* <pre> {@code
* if (map.containsKey(key) && map.get(key).equals(value)) {
* if (map.containsKey(key) && Objects.equals(map.get(key), value)) {
* map.remove(key);
* return true;
* } else
......@@ -101,8 +116,8 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
*
* @param key key with which the specified value is associated
* @param value value expected to be associated with the specified key
* @return <tt>true</tt> if the value was removed
* @throws UnsupportedOperationException if the <tt>remove</tt> operation
* @return {@code true} if the value was removed
* @throws UnsupportedOperationException if the {@code remove} operation
* is not supported by this map
* @throws ClassCastException if the key or value is of an inappropriate
* type for this map
......@@ -117,7 +132,7 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* Replaces the entry for a key only if currently mapped to a given value.
* This is equivalent to
* <pre> {@code
* if (map.containsKey(key) && map.get(key).equals(oldValue)) {
* if (map.containsKey(key) && Objects.equals(map.get(key), oldValue)) {
* map.put(key, newValue);
* return true;
* } else
......@@ -128,8 +143,8 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* @param key key with which the specified value is associated
* @param oldValue value expected to be associated with the specified key
* @param newValue value to be associated with the specified key
* @return <tt>true</tt> if the value was replaced
* @throws UnsupportedOperationException if the <tt>put</tt> operation
* @return {@code true} if the value was replaced
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of a specified key or value
* prevents it from being stored in this map
......@@ -154,11 +169,11 @@ public interface ConcurrentMap<K, V> extends Map<K, V> {
* @param key key with which the specified value is associated
* @param value value to be associated with the specified key
* @return the previous value associated with the specified key, or
* <tt>null</tt> if there was no mapping for the key.
* (A <tt>null</tt> return can also indicate that the map
* previously associated <tt>null</tt> with the key,
* {@code null} if there was no mapping for the key.
* (A {@code null} return can also indicate that the map
* previously associated {@code null} with the key,
* if the implementation supports null values.)
* @throws UnsupportedOperationException if the <tt>put</tt> operation
* @throws UnsupportedOperationException if the {@code put} operation
* is not supported by this map
* @throws ClassCastException if the class of the specified key or value
* prevents it from being stored in this map
......
此差异已折叠。
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册