mirror of
https://github.com/OpenHFT/Chronicle-Map.git
synced 2021-09-13 01:26:12 +00:00
HCOLL-119 removed the use of " public <K, V> SharedHashMap<K, V> create(File file, Class<K> kClass, Class<V> vClass) "
This commit is contained in:
@@ -106,7 +106,6 @@ public interface ChronicleMap<K, V> extends SharedHashMap<K, V>, ConcurrentMapLa
|
||||
*/
|
||||
default void replaceAll(BiFunction<? super K, ? super V, ? extends V> function) {
|
||||
Objects.requireNonNull(function);
|
||||
|
||||
final BiConsumer<K, V> action = (k, v) -> {
|
||||
while (!replace(k, v, function.apply(k, v))) {
|
||||
// v changed or k is gone
|
||||
|
||||
@@ -88,9 +88,9 @@ import java.util.stream.Stream;
|
||||
* same {@code hashCode()} is a sure way to slow down performance of any hash table. To ameliorate impact,
|
||||
* when keys are {@link Comparable}, this class may use comparison order among keys to help break ties.
|
||||
*
|
||||
* <p>A {@link Set} projection of a ConcurrentHashMap may be created (using {@link #newKeySet()} or {@link
|
||||
* #newKeySet(int)}), or viewed (using {@link #keySet(Object)} when only keys are of interest, and the mapped
|
||||
* values are (perhaps transiently) not used or all take the same mapping value.
|
||||
* <p>A {@link Set} projection of a ConcurrentHashMap may be created (using {@link )} or {@link # (int)}), or
|
||||
* viewed (using {@link # (Object)} when only keys are of interest, and the mapped values are (perhaps
|
||||
* transiently) not used or all take the same mapping value.
|
||||
*
|
||||
* <p>A ConcurrentHashMap can be used as scalable frequency map (a form of histogram or multiset) by using
|
||||
* {@link java.util.concurrent.atomic.LongAdder} values and initializing via {@link #computeIfAbsent
|
||||
@@ -183,7 +183,7 @@ import java.util.stream.Stream;
|
||||
* @author Doug Lea
|
||||
* @since 1.5
|
||||
*/
|
||||
public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
implements ConcurrentMap<K, V>, Serializable {
|
||||
private static final long serialVersionUID = 7249069246763182397L;
|
||||
|
||||
@@ -722,10 +722,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
*/
|
||||
private transient volatile CounterCell[] counterCells;
|
||||
|
||||
// views
|
||||
private transient KeySetView<K, V> keySet;
|
||||
private transient ValuesView<K, V> values;
|
||||
private transient EntrySetView<K, V> entrySet;
|
||||
|
||||
|
||||
/* ---------------- Public operations -------------- */
|
||||
@@ -822,7 +818,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}*/
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, or {@code null} if this map contains no mapping
|
||||
* for the key.
|
||||
@@ -910,7 +905,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
/**
|
||||
* Implementation for put and putIfAbsent
|
||||
*/
|
||||
final V putVal(K key, V value, boolean onlyIfAbsent) {
|
||||
V putVal(K key, V value, boolean onlyIfAbsent) {
|
||||
if (key == null || value == null) throw new NullPointerException();
|
||||
int hash = spread(key.hashCode());
|
||||
int binCount = 0;
|
||||
@@ -1107,64 +1102,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
addCount(delta, -1);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} view of the keys contained in this map. The set is backed by the map, so changes
|
||||
* to the map are reflected in the set, and vice-versa. The set supports element removal, which removes
|
||||
* the corresponding mapping from this map, via the {@code Iterator.remove}, {@code Set.remove}, {@code
|
||||
* removeAll}, {@code retainAll}, and {@code clear} operations. It does not support the {@code add} or
|
||||
* {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are <a href="package-summary.html#Weakly"><i>weakly
|
||||
* consistent</i></a>.
|
||||
*
|
||||
* <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT},
|
||||
* and {@link Spliterator#NONNULL}.
|
||||
*
|
||||
* @return the set view
|
||||
*/
|
||||
public KeySetView<K, V> keySet() {
|
||||
KeySetView<K, V> ks;
|
||||
return (ks = keySet) != null ? ks : (keySet = new KeySetView<K, V>(this, null));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Collection} view of the values contained in this map. The collection is backed by the
|
||||
* map, so changes to the map are reflected in the collection, and vice-versa. The collection supports
|
||||
* element removal, which removes the corresponding mapping from this map, via the {@code
|
||||
* Iterator.remove}, {@code Collection.remove}, {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are <a href="package-summary.html#Weakly"><i>weakly
|
||||
* consistent</i></a>.
|
||||
*
|
||||
* <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT} and {@link
|
||||
* Spliterator#NONNULL}.
|
||||
*
|
||||
* @return the collection view
|
||||
*/
|
||||
public Collection<V> values() {
|
||||
ValuesView<K, V> vs;
|
||||
return (vs = values) != null ? vs : (values = new ValuesView<K, V>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} view of the mappings contained in this map. The set is backed by the map, so
|
||||
* changes to the map are reflected in the set, and vice-versa. The set supports element removal, which
|
||||
* removes the corresponding mapping from the map, via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear} operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are <a href="package-summary.html#Weakly"><i>weakly
|
||||
* consistent</i></a>.
|
||||
*
|
||||
* <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT},
|
||||
* and {@link Spliterator#NONNULL}.
|
||||
*
|
||||
* @return the set view
|
||||
*/
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
EntrySetView<K, V> es;
|
||||
return (es = entrySet) != null ? es : (entrySet = new EntrySetView<K, V>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the hash code value for this {@link Map}, i.e., the sum of, for each key-value pair in the map,
|
||||
@@ -1471,10 +1408,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* If the value for the specified key is present, attempts to compute a new mapping given the key and its
|
||||
* current mapped value. The entire method invocation is performed atomically. Some attempted update
|
||||
@@ -1560,226 +1493,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* Attempts to compute a mapping for the specified key and its current mapped value (or {@code null} if
|
||||
* there is no current mapping). The entire method invocation is performed atomically. Some attempted
|
||||
* update operations on this map by other threads may be blocked while computation is in progress, so the
|
||||
* computation should be short and simple, and must not attempt to update any other mappings of this Map.
|
||||
*
|
||||
* @param key key with which the specified value is to be associated
|
||||
* @param remappingFunction the function to compute a value
|
||||
* @return the new value associated with the specified key, or null if none
|
||||
* @throws NullPointerException if the specified key or remappingFunction is null
|
||||
* @throws IllegalStateException if the computation detectably attempts a recursive update to this map
|
||||
* that would otherwise never complete
|
||||
* @throws RuntimeException or Error if the remappingFunction does so, in which case the mapping is
|
||||
* unchanged
|
||||
*/
|
||||
public V compute(K key,
|
||||
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
|
||||
if (key == null || remappingFunction == null)
|
||||
throw new NullPointerException();
|
||||
int h = spread(key.hashCode());
|
||||
V val = null;
|
||||
int delta = 0;
|
||||
int binCount = 0;
|
||||
for (Node<K, V>[] tab = table; ; ) {
|
||||
Node<K, V> f;
|
||||
int n, i, fh;
|
||||
if (tab == null || (n = tab.length) == 0)
|
||||
tab = initTable();
|
||||
else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
|
||||
Node<K, V> r = new ReservationNode<K, V>();
|
||||
synchronized (r) {
|
||||
if (casTabAt(tab, i, null, r)) {
|
||||
binCount = 1;
|
||||
Node<K, V> node = null;
|
||||
try {
|
||||
if ((val = remappingFunction.apply(key, null)) != null) {
|
||||
delta = 1;
|
||||
node = new Node<K, V>(h, key, val, null);
|
||||
}
|
||||
} finally {
|
||||
setTabAt(tab, i, node);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binCount != 0)
|
||||
break;
|
||||
} else if ((fh = f.hash) == MOVED)
|
||||
tab = helpTransfer(tab, f);
|
||||
else {
|
||||
synchronized (f) {
|
||||
if (tabAt(tab, i) == f) {
|
||||
if (fh >= 0) {
|
||||
binCount = 1;
|
||||
for (Node<K, V> e = f, pred = null; ; ++binCount) {
|
||||
K ek;
|
||||
if (e.hash == h &&
|
||||
((ek = e.key) == key ||
|
||||
(ek != null && key.equals(ek)))) {
|
||||
val = remappingFunction.apply(key, e.val);
|
||||
if (val != null)
|
||||
e.val = val;
|
||||
else {
|
||||
delta = -1;
|
||||
Node<K, V> en = e.next;
|
||||
if (pred != null)
|
||||
pred.next = en;
|
||||
else
|
||||
setTabAt(tab, i, en);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pred = e;
|
||||
if ((e = e.next) == null) {
|
||||
val = remappingFunction.apply(key, null);
|
||||
if (val != null) {
|
||||
delta = 1;
|
||||
pred.next =
|
||||
new Node<K, V>(h, key, val, null);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (f instanceof TreeBin) {
|
||||
binCount = 1;
|
||||
TreeBin<K, V> t = (TreeBin<K, V>) f;
|
||||
TreeNode<K, V> r, p;
|
||||
if ((r = t.root) != null)
|
||||
p = r.findTreeNode(h, key, null);
|
||||
else
|
||||
p = null;
|
||||
V pv = (p == null) ? null : p.val;
|
||||
val = remappingFunction.apply(key, pv);
|
||||
if (val != null) {
|
||||
if (p != null)
|
||||
p.val = val;
|
||||
else {
|
||||
delta = 1;
|
||||
t.putTreeVal(h, key, val);
|
||||
}
|
||||
} else if (p != null) {
|
||||
delta = -1;
|
||||
if (t.removeTreeNode(p))
|
||||
setTabAt(tab, i, untreeify(t.first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binCount != 0) {
|
||||
if (binCount >= TREEIFY_THRESHOLD)
|
||||
treeifyBin(tab, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (delta != 0)
|
||||
addCount((long) delta, binCount);
|
||||
return val;
|
||||
}
|
||||
|
||||
/**
|
||||
* If the specified key is not already associated with a (non-null) value, associates it with the given
|
||||
* value. Otherwise, replaces the value with the results of the given remapping function, or removes if
|
||||
* {@code null}. The entire method invocation is performed atomically. Some attempted update operations
|
||||
* on this map by other threads may be blocked while computation is in progress, so the computation should
|
||||
* be short and simple, and must not attempt to update any other mappings of this Map.
|
||||
*
|
||||
* @param key key with which the specified value is to be associated
|
||||
* @param value the value to use if absent
|
||||
* @param remappingFunction the function to recompute a value if present
|
||||
* @return the new value associated with the specified key, or null if none
|
||||
* @throws NullPointerException if the specified key or the remappingFunction is null
|
||||
* @throws RuntimeException or Error if the remappingFunction does so, in which case the mapping is
|
||||
* unchanged
|
||||
*/
|
||||
public V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
|
||||
if (key == null || value == null || remappingFunction == null)
|
||||
throw new NullPointerException();
|
||||
int h = spread(key.hashCode());
|
||||
V val = null;
|
||||
int delta = 0;
|
||||
int binCount = 0;
|
||||
for (Node<K, V>[] tab = table; ; ) {
|
||||
Node<K, V> f;
|
||||
int n, i, fh;
|
||||
if (tab == null || (n = tab.length) == 0)
|
||||
tab = initTable();
|
||||
else if ((f = tabAt(tab, i = (n - 1) & h)) == null) {
|
||||
if (casTabAt(tab, i, null, new Node<K, V>(h, key, value, null))) {
|
||||
delta = 1;
|
||||
val = value;
|
||||
break;
|
||||
}
|
||||
} else if ((fh = f.hash) == MOVED)
|
||||
tab = helpTransfer(tab, f);
|
||||
else {
|
||||
synchronized (f) {
|
||||
if (tabAt(tab, i) == f) {
|
||||
if (fh >= 0) {
|
||||
binCount = 1;
|
||||
for (Node<K, V> e = f, pred = null; ; ++binCount) {
|
||||
K ek;
|
||||
if (e.hash == h &&
|
||||
((ek = e.key) == key ||
|
||||
(ek != null && key.equals(ek)))) {
|
||||
val = remappingFunction.apply(e.val, value);
|
||||
if (val != null)
|
||||
e.val = val;
|
||||
else {
|
||||
delta = -1;
|
||||
Node<K, V> en = e.next;
|
||||
if (pred != null)
|
||||
pred.next = en;
|
||||
else
|
||||
setTabAt(tab, i, en);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pred = e;
|
||||
if ((e = e.next) == null) {
|
||||
delta = 1;
|
||||
val = value;
|
||||
pred.next =
|
||||
new Node<K, V>(h, key, val, null);
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (f instanceof TreeBin) {
|
||||
binCount = 2;
|
||||
TreeBin<K, V> t = (TreeBin<K, V>) f;
|
||||
TreeNode<K, V> r = t.root;
|
||||
TreeNode<K, V> p = (r == null) ? null :
|
||||
r.findTreeNode(h, key, null);
|
||||
val = (p == null) ? value :
|
||||
remappingFunction.apply(p.val, value);
|
||||
if (val != null) {
|
||||
if (p != null)
|
||||
p.val = val;
|
||||
else {
|
||||
delta = 1;
|
||||
t.putTreeVal(h, key, val);
|
||||
}
|
||||
} else if (p != null) {
|
||||
delta = -1;
|
||||
if (t.removeTreeNode(p))
|
||||
setTabAt(tab, i, untreeify(t.first));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (binCount != 0) {
|
||||
if (binCount >= TREEIFY_THRESHOLD)
|
||||
treeifyBin(tab, i);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (delta != 0)
|
||||
addCount((long) delta, binCount);
|
||||
return val;
|
||||
}
|
||||
|
||||
// Hashtable legacy methods
|
||||
|
||||
@@ -1837,46 +1550,7 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
return (n < 0L) ? 0L : n; // ignore transient negative values
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}.
|
||||
*
|
||||
* @param <K> the element type of the returned set
|
||||
* @return the new set
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <K> KeySetView<K, Boolean> newKeySet() {
|
||||
return new KeySetView<K, Boolean>
|
||||
(new ConcurrentHashMap<K, Boolean>(), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}.
|
||||
*
|
||||
* @param initialCapacity The implementation performs internal sizing to accommodate this many elements.
|
||||
* @param <K> the element type of the returned set
|
||||
* @return the new set
|
||||
* @throws IllegalArgumentException if the initial capacity of elements is negative
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <K> KeySetView<K, Boolean> newKeySet(int initialCapacity) {
|
||||
return new KeySetView<K, Boolean>
|
||||
(new ConcurrentHashMap<K, Boolean>(initialCapacity), Boolean.TRUE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} view of the keys in this map, using the given common mapped value for any
|
||||
* additions (i.e., {@link Collection#add} and {@link Collection#addAll(Collection)}). This is of course
|
||||
* only appropriate if it is acceptable to use the same value for all additions from this view.
|
||||
*
|
||||
* @param mappedValue the mapped value to use for any additions
|
||||
* @return the set view
|
||||
* @throws NullPointerException if the mappedValue is null
|
||||
*/
|
||||
public KeySetView<K, V> keySet(V mappedValue) {
|
||||
if (mappedValue == null)
|
||||
throw new NullPointerException();
|
||||
return new KeySetView<K, V>(this, mappedValue);
|
||||
}
|
||||
|
||||
/* ---------------- Special Nodes -------------- */
|
||||
|
||||
@@ -3412,464 +3086,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
// Parallel bulk operations
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/* ----------------Views -------------- */
|
||||
|
||||
/**
|
||||
* Base class for views.
|
||||
*/
|
||||
abstract static class CollectionView<K, V, E>
|
||||
implements Collection<E>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 7249069246763182397L;
|
||||
final ConcurrentHashMap<K, V> map;
|
||||
|
||||
CollectionView(ConcurrentHashMap<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map backing this view.
|
||||
*
|
||||
* @return the map backing this view
|
||||
*/
|
||||
public ConcurrentHashMap<K, V> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this view, by removing all the mappings from the map backing this
|
||||
* view.
|
||||
*/
|
||||
public final void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public final int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public final boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
// implementations below rely on concrete classes supplying these
|
||||
// abstract methods
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this collection.
|
||||
*
|
||||
* <p>The returned iterator is <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* @return an iterator over the elements in this collection
|
||||
*/
|
||||
public abstract Iterator<E> iterator();
|
||||
|
||||
public abstract boolean contains(Object o);
|
||||
|
||||
public abstract boolean remove(Object o);
|
||||
|
||||
private static final String oomeMsg = "Required array size too large";
|
||||
|
||||
public final Object[] toArray() {
|
||||
long sz = map.mappingCount();
|
||||
if (sz > MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
int n = (int) sz;
|
||||
Object[] r = new Object[n];
|
||||
int i = 0;
|
||||
for (E e : this) {
|
||||
if (i == n) {
|
||||
if (n >= MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
|
||||
n = MAX_ARRAY_SIZE;
|
||||
else
|
||||
n += (n >>> 1) + 1;
|
||||
r = Arrays.copyOf(r, n);
|
||||
}
|
||||
r[i++] = e;
|
||||
}
|
||||
return (i == n) ? r : Arrays.copyOf(r, i);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T> T[] toArray(T[] a) {
|
||||
long sz = map.mappingCount();
|
||||
if (sz > MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
int m = (int) sz;
|
||||
T[] r = (a.length >= m) ? a :
|
||||
(T[]) java.lang.reflect.Array
|
||||
.newInstance(a.getClass().getComponentType(), m);
|
||||
int n = r.length;
|
||||
int i = 0;
|
||||
for (E e : this) {
|
||||
if (i == n) {
|
||||
if (n >= MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
|
||||
n = MAX_ARRAY_SIZE;
|
||||
else
|
||||
n += (n >>> 1) + 1;
|
||||
r = Arrays.copyOf(r, n);
|
||||
}
|
||||
r[i++] = (T) e;
|
||||
}
|
||||
if (a == r && i < n) {
|
||||
r[i] = null; // null-terminate
|
||||
return r;
|
||||
}
|
||||
return (i == n) ? r : Arrays.copyOf(r, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this collection. The string representation consists of the
|
||||
* string representations of the collection's elements in the order they are returned by its iterator,
|
||||
* enclosed in square brackets ({@code "[]"}). Adjacent elements are separated by the characters
|
||||
* {@code ", "} (comma and space). Elements are converted to strings as by {@link
|
||||
* String#valueOf(Object)}.
|
||||
*
|
||||
* @return a string representation of this collection
|
||||
*/
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[');
|
||||
Iterator<E> it = iterator();
|
||||
if (it.hasNext()) {
|
||||
for (; ; ) {
|
||||
Object e = it.next();
|
||||
sb.append(e == this ? "(this Collection)" : e);
|
||||
if (!it.hasNext())
|
||||
break;
|
||||
sb.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
return sb.append(']').toString();
|
||||
}
|
||||
|
||||
public final boolean containsAll(Collection<?> c) {
|
||||
if (c != this) {
|
||||
for (Object e : c) {
|
||||
if (e == null || !contains(e))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean removeAll(Collection<?> c) {
|
||||
if (c == null) throw new NullPointerException();
|
||||
boolean modified = false;
|
||||
for (Iterator<E> it = iterator(); it.hasNext(); ) {
|
||||
if (c.contains(it.next())) {
|
||||
it.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
public final boolean retainAll(Collection<?> c) {
|
||||
if (c == null) throw new NullPointerException();
|
||||
boolean modified = false;
|
||||
for (Iterator<E> it = iterator(); it.hasNext(); ) {
|
||||
if (!c.contains(it.next())) {
|
||||
it.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* A view of a ConcurrentHashMap as a {@link Set} of keys, in which additions may optionally be enabled by
|
||||
* mapping to a common value. This class cannot be directly instantiated. See {@link #keySet() keySet()},
|
||||
* {@link #keySet(Object) keySet(V)}, {@link #newKeySet() newKeySet()}, {@link #newKeySet(int)
|
||||
* newKeySet(int)}.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class KeySetView<K, V> extends CollectionView<K, V, K>
|
||||
implements Set<K>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 7249069246763182397L;
|
||||
private final V value;
|
||||
|
||||
KeySetView(ConcurrentHashMap<K, V> map, V value) { // non-public
|
||||
super(map);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default mapped value for additions, or {@code null} if additions are not supported.
|
||||
*
|
||||
* @return the default mapped value for additions, or {@code null} if not supported
|
||||
*/
|
||||
public V getMappedValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return map.containsKey(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the key from this map view, by removing the key (and its corresponding value) from the
|
||||
* backing map. This method does nothing if the key is not in the map.
|
||||
*
|
||||
* @param o the key to be removed from the backing map
|
||||
* @return {@code true} if the backing map contained the specified key
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
return map.remove(o) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterator over the keys of the backing map
|
||||
*/
|
||||
public Iterator<K> iterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new KeyIterator<K, V>(t, f, 0, f, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified key to this set view by mapping the key to the default mapped value in the
|
||||
* backing map, if defined.
|
||||
*
|
||||
* @param e key to be added
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the specified key is null
|
||||
* @throws UnsupportedOperationException if no default mapped value for additions was provided
|
||||
*/
|
||||
public boolean add(K e) {
|
||||
V v;
|
||||
if ((v = value) == null)
|
||||
throw new UnsupportedOperationException();
|
||||
return map.putVal(e, v, true) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the elements in the specified collection to this set, as if by calling {@link #add} on
|
||||
* each one.
|
||||
*
|
||||
* @param c the elements to be inserted into this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the collection or any of its elements are {@code null}
|
||||
* @throws UnsupportedOperationException if no default mapped value for additions was provided
|
||||
*/
|
||||
public boolean addAll(Collection<? extends K> c) {
|
||||
boolean added = false;
|
||||
V v;
|
||||
if ((v = value) == null)
|
||||
throw new UnsupportedOperationException();
|
||||
for (K e : c) {
|
||||
if (map.putVal(e, v, true) == null)
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int h = 0;
|
||||
for (K e : this)
|
||||
h += e.hashCode();
|
||||
return h;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
Set<?> c;
|
||||
return ((o instanceof Set) &&
|
||||
((c = (Set<?>) o) == this ||
|
||||
(containsAll(c) && c.containsAll(this))));
|
||||
}
|
||||
|
||||
public Spliterator<K> spliterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
long n = m.sumCount();
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new KeySpliterator<K, V>(t, f, 0, f, n < 0L ? 0L : n);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super K> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; )
|
||||
action.accept(p.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A view of a ConcurrentHashMap as a {@link Collection} of values, in which additions are disabled. This
|
||||
* class cannot be directly instantiated. See {@link #values()}.
|
||||
*/
|
||||
static final class ValuesView<K, V> extends CollectionView<K, V, V>
|
||||
implements Collection<V>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 2249069246763182397L;
|
||||
|
||||
ValuesView(ConcurrentHashMap<K, V> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public final boolean contains(Object o) {
|
||||
return map.containsValue(o);
|
||||
}
|
||||
|
||||
public final boolean remove(Object o) {
|
||||
if (o != null) {
|
||||
for (Iterator<V> it = iterator(); it.hasNext(); ) {
|
||||
if (o.equals(it.next())) {
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final Iterator<V> iterator() {
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
Node<K, V>[] t;
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new ValueIterator<K, V>(t, f, 0, f, m);
|
||||
}
|
||||
|
||||
public final boolean add(V e) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final boolean addAll(Collection<? extends V> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Spliterator<V> spliterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
long n = m.sumCount();
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new ValueSpliterator<K, V>(t, f, 0, f, n < 0L ? 0L : n);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super V> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; )
|
||||
action.accept(p.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A view of a ConcurrentHashMap as a {@link Set} of (key, value) entries. This class cannot be directly
|
||||
* instantiated. See {@link #entrySet()}.
|
||||
*/
|
||||
static final class EntrySetView<K, V> extends CollectionView<K, V, Map.Entry<K, V>>
|
||||
implements Set<Map.Entry<K, V>>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 2249069246763182397L;
|
||||
|
||||
EntrySetView(ConcurrentHashMap<K, V> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
Object k, v, r;
|
||||
Map.Entry<?, ?> e;
|
||||
return ((o instanceof Map.Entry) &&
|
||||
(k = (e = (Map.Entry<?, ?>) o).getKey()) != null &&
|
||||
(r = map.get(k)) != null &&
|
||||
(v = e.getValue()) != null &&
|
||||
(v == r || v.equals(r)));
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
Object k, v;
|
||||
Map.Entry<?, ?> e;
|
||||
return ((o instanceof Map.Entry) &&
|
||||
(k = (e = (Map.Entry<?, ?>) o).getKey()) != null &&
|
||||
(v = e.getValue()) != null &&
|
||||
map.remove(k, v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterator over the entries of the backing map
|
||||
*/
|
||||
public Iterator<Map.Entry<K, V>> iterator() {
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
Node<K, V>[] t;
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new EntryIterator<K, V>(t, f, 0, f, m);
|
||||
}
|
||||
|
||||
public boolean add(Entry<K, V> e) {
|
||||
return map.putVal(e.getKey(), e.getValue(), false) == null;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends Entry<K, V>> c) {
|
||||
boolean added = false;
|
||||
for (Entry<K, V> e : c) {
|
||||
if (add(e))
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public final int hashCode() {
|
||||
int h = 0;
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; ) {
|
||||
h += p.hashCode();
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public final boolean equals(Object o) {
|
||||
Set<?> c;
|
||||
return ((o instanceof Set) &&
|
||||
((c = (Set<?>) o) == this ||
|
||||
(containsAll(c) && c.containsAll(this))));
|
||||
}
|
||||
|
||||
public Spliterator<Map.Entry<K, V>> spliterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
long n = m.sumCount();
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new EntrySpliterator<K, V>(t, f, 0, f, n < 0L ? 0L : n, m);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super Map.Entry<K, V>> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; )
|
||||
action.accept(new MapEntry<K, V>(p.key, p.val, map));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// -------------------------------------------------------
|
||||
|
||||
/**
|
||||
@@ -4384,7 +3600,6 @@ public class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}
|
||||
|
||||
|
||||
|
||||
@SuppressWarnings("serial")
|
||||
static final class ReduceKeysTask<K, V>
|
||||
extends BulkTask<K, V, K> {
|
||||
|
||||
@@ -42,12 +42,12 @@ public interface ConcurrentMapLamdadSupport<K, V> {
|
||||
*
|
||||
* @return the set view
|
||||
*/
|
||||
public net.openhft.collections.ConcurrentHashMap.KeySetView<K, V> keySet();
|
||||
AbstractVanillaSharedMap.KeySetView<K, V> keySet();
|
||||
|
||||
|
||||
long mappingCount();
|
||||
|
||||
net.openhft.collections.ConcurrentHashMap.KeySetView<K, V> keySet(V mappedValue);
|
||||
net.openhft.collections.KeySetView<K, V> keySet(V mappedValue);
|
||||
|
||||
void forEach(long parallelismThreshold,
|
||||
BiConsumer<? super K, ? super V> action);
|
||||
|
||||
@@ -0,0 +1,89 @@
|
||||
/*
|
||||
* Copyright 2014 Higher Frequency Trading
|
||||
* <p/>
|
||||
* http://www.higherfrequencytrading.com
|
||||
* <p/>
|
||||
* Licensed under the Apache License, Version 2.0 (the "License");
|
||||
* you may not use this file except in compliance with the License.
|
||||
* You may obtain a copy of the License at
|
||||
* <p/>
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* <p/>
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
|
||||
package net.openhft.collections;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Iterator;
|
||||
import java.util.Set;
|
||||
import java.util.Spliterator;
|
||||
import java.util.function.Consumer;
|
||||
|
||||
/**
|
||||
* @author Rob Austin.
|
||||
*/
|
||||
public interface KeySetView<K, V> extends Collection<K>, java.io.Serializable, Set<K> {
|
||||
/**
|
||||
* Returns the default mapped value for additions, or {@code null} if additions are not supported.
|
||||
*
|
||||
* @return the default mapped value for additions, or {@code null} if not supported
|
||||
*/
|
||||
V getMappedValue();
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
boolean contains(Object o);
|
||||
|
||||
/**
|
||||
* Removes the key from this map view, by removing the key (and its corresponding value) from the backing
|
||||
* map. This method does nothing if the key is not in the map.
|
||||
*
|
||||
* @param o the key to be removed from the backing map
|
||||
* @return {@code true} if the backing map contained the specified key
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
boolean remove(Object o);
|
||||
|
||||
/**
|
||||
* @return an iterator over the keys of the backing map
|
||||
*/
|
||||
Iterator<K> iterator();
|
||||
|
||||
/**
|
||||
* Adds the specified key to this set view by mapping the key to the default mapped value in the backing
|
||||
* map, if defined.
|
||||
*
|
||||
* @param e key to be added
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the specified key is null
|
||||
* @throws UnsupportedOperationException if no default mapped value for additions was provided
|
||||
*/
|
||||
boolean add(K e);
|
||||
|
||||
/**
|
||||
* Adds all of the elements in the specified collection to this set, as if by calling {@link #add} on each
|
||||
* one.
|
||||
*
|
||||
* @param c the elements to be inserted into this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the collection or any of its elements are {@code null}
|
||||
* @throws UnsupportedOperationException if no default mapped value for additions was provided
|
||||
*/
|
||||
boolean addAll(Collection<? extends K> c);
|
||||
|
||||
int hashCode();
|
||||
|
||||
boolean equals(Object o);
|
||||
|
||||
Spliterator<K> spliterator();
|
||||
|
||||
void forEach(Consumer<? super K> action);
|
||||
}
|
||||
@@ -28,7 +28,6 @@ import net.openhft.lang.io.serialization.ObjectSerializer;
|
||||
import net.openhft.lang.io.serialization.impl.VanillaBytesMarshallerFactory;
|
||||
import net.openhft.lang.model.Byteable;
|
||||
import net.openhft.lang.model.DataValueClasses;
|
||||
import net.openhft.lang.model.constraints.NotNull;
|
||||
import net.openhft.lang.model.constraints.Nullable;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@@ -72,11 +71,542 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
private SharedHashMapBuilder builder;
|
||||
|
||||
|
||||
// views
|
||||
|
||||
transient ValuesView<K, V> values;
|
||||
transient EntrySetView<K, V> entrySet;
|
||||
transient KeySetView<K, V> keySet;
|
||||
|
||||
|
||||
/* ----------------Views -------------- */
|
||||
|
||||
/**
|
||||
* Base class for views.
|
||||
*/
|
||||
abstract static class CollectionView<K, V, E>
|
||||
implements Collection<E>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 7249069246763182397L;
|
||||
final AbstractVanillaSharedMap<K, V> map;
|
||||
|
||||
CollectionView(AbstractVanillaSharedMap<K, V> map) {
|
||||
this.map = map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the map backing this view.
|
||||
*
|
||||
* @return the map backing this view
|
||||
*/
|
||||
public AbstractVanillaSharedMap<K, V> getMap() {
|
||||
return map;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the elements from this view, by removing all the mappings from the map backing this
|
||||
* view.
|
||||
*/
|
||||
public final void clear() {
|
||||
map.clear();
|
||||
}
|
||||
|
||||
public final int size() {
|
||||
return map.size();
|
||||
}
|
||||
|
||||
public final boolean isEmpty() {
|
||||
return map.isEmpty();
|
||||
}
|
||||
|
||||
// implementations below rely on concrete classes supplying these
|
||||
// abstract methods
|
||||
|
||||
/**
|
||||
* Returns an iterator over the elements in this collection.
|
||||
*
|
||||
* <p>The returned iterator is <a href="package-summary.html#Weakly"><i>weakly consistent</i></a>.
|
||||
*
|
||||
* @return an iterator over the elements in this collection
|
||||
*/
|
||||
public abstract Iterator<E> iterator();
|
||||
|
||||
public abstract boolean contains(Object o);
|
||||
|
||||
public abstract boolean remove(Object o);
|
||||
|
||||
private static final String oomeMsg = "Required array size too large";
|
||||
|
||||
public final Object[] toArray() {
|
||||
long sz = map.mappingCount();
|
||||
if (sz > MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
int n = (int) sz;
|
||||
Object[] r = new Object[n];
|
||||
int i = 0;
|
||||
for (E e : this) {
|
||||
if (i == n) {
|
||||
if (n >= MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
|
||||
n = MAX_ARRAY_SIZE;
|
||||
else
|
||||
n += (n >>> 1) + 1;
|
||||
r = Arrays.copyOf(r, n);
|
||||
}
|
||||
r[i++] = e;
|
||||
}
|
||||
return (i == n) ? r : Arrays.copyOf(r, i);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
public final <T> T[] toArray(T[] a) {
|
||||
long sz = map.mappingCount();
|
||||
if (sz > MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
int m = (int) sz;
|
||||
T[] r = (a.length >= m) ? a :
|
||||
(T[]) java.lang.reflect.Array
|
||||
.newInstance(a.getClass().getComponentType(), m);
|
||||
int n = r.length;
|
||||
int i = 0;
|
||||
for (E e : this) {
|
||||
if (i == n) {
|
||||
if (n >= MAX_ARRAY_SIZE)
|
||||
throw new OutOfMemoryError(oomeMsg);
|
||||
if (n >= MAX_ARRAY_SIZE - (MAX_ARRAY_SIZE >>> 1) - 1)
|
||||
n = MAX_ARRAY_SIZE;
|
||||
else
|
||||
n += (n >>> 1) + 1;
|
||||
r = Arrays.copyOf(r, n);
|
||||
}
|
||||
r[i++] = (T) e;
|
||||
}
|
||||
if (a == r && i < n) {
|
||||
r[i] = null; // null-terminate
|
||||
return r;
|
||||
}
|
||||
return (i == n) ? r : Arrays.copyOf(r, i);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this collection. The string representation consists of the
|
||||
* string representations of the collection's elements in the order they are returned by its iterator,
|
||||
* enclosed in square brackets ({@code "[]"}). Adjacent elements are separated by the characters
|
||||
* {@code ", "} (comma and space). Elements are converted to strings as by {@link
|
||||
* String#valueOf(Object)}.
|
||||
*
|
||||
* @return a string representation of this collection
|
||||
*/
|
||||
public final String toString() {
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('[');
|
||||
Iterator<E> it = iterator();
|
||||
if (it.hasNext()) {
|
||||
for (; ; ) {
|
||||
Object e = it.next();
|
||||
sb.append(e == this ? "(this Collection)" : e);
|
||||
if (!it.hasNext())
|
||||
break;
|
||||
sb.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
return sb.append(']').toString();
|
||||
}
|
||||
|
||||
public final boolean containsAll(Collection<?> c) {
|
||||
if (c != this) {
|
||||
for (Object e : c) {
|
||||
if (e == null || !contains(e))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
public final boolean removeAll(Collection<?> c) {
|
||||
if (c == null) throw new NullPointerException();
|
||||
boolean modified = false;
|
||||
for (Iterator<E> it = iterator(); it.hasNext(); ) {
|
||||
if (c.contains(it.next())) {
|
||||
it.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
public final boolean retainAll(Collection<?> c) {
|
||||
if (c == null) throw new NullPointerException();
|
||||
boolean modified = false;
|
||||
for (Iterator<E> it = iterator(); it.hasNext(); ) {
|
||||
if (!c.contains(it.next())) {
|
||||
it.remove();
|
||||
modified = true;
|
||||
}
|
||||
}
|
||||
return modified;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* A view of a ConcurrentHashMap as a {@link Collection} of values, in which additions are disabled. This
|
||||
* class cannot be directly instantiated. See {@link #values()}.
|
||||
*/
|
||||
static final class ValuesView<K, V> extends CollectionView<K, V, V>
|
||||
implements Collection<V>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 2249069246763182397L;
|
||||
|
||||
ValuesView(AbstractVanillaSharedMap<K, V> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public final boolean contains(Object o) {
|
||||
return map.containsValue(o);
|
||||
}
|
||||
|
||||
public final boolean remove(Object o) {
|
||||
if (o != null) {
|
||||
for (Iterator<V> it = iterator(); it.hasNext(); ) {
|
||||
if (o.equals(it.next())) {
|
||||
it.remove();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public final Iterator<V> iterator() {
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
Node<K, V>[] t;
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new ValueIterator<K, V>(t, f, 0, f, m);
|
||||
}
|
||||
|
||||
public final boolean add(V e) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public final boolean addAll(Collection<? extends V> c) {
|
||||
throw new UnsupportedOperationException();
|
||||
}
|
||||
|
||||
public Spliterator<V> spliterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
long n = m.sumCount();
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new ValueSpliterator<K, V>(t, f, 0, f, n < 0L ? 0L : n);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super V> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; )
|
||||
action.accept(p.val);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* A view of a ConcurrentHashMap as a {@link Set} of (key, value) entries. This class cannot be directly
|
||||
* instantiated. See {@link #entrySet()}.
|
||||
*/
|
||||
static final class EntrySetView<K, V> extends CollectionView<K, V, Map.Entry<K, V>>
|
||||
implements Set<Map.Entry<K, V>>, java.io.Serializable {
|
||||
private static final long serialVersionUID = 2249069246763182397L;
|
||||
|
||||
EntrySetView(AbstractVanillaSharedMap<K, V> map) {
|
||||
super(map);
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
Object k, v, r;
|
||||
Map.Entry<?, ?> e;
|
||||
return ((o instanceof Map.Entry) &&
|
||||
(k = (e = (Map.Entry<?, ?>) o).getKey()) != null &&
|
||||
(r = map.get(k)) != null &&
|
||||
(v = e.getValue()) != null &&
|
||||
(v == r || v.equals(r)));
|
||||
}
|
||||
|
||||
public boolean remove(Object o) {
|
||||
Object k, v;
|
||||
Map.Entry<?, ?> e;
|
||||
return ((o instanceof Map.Entry) &&
|
||||
(k = (e = (Map.Entry<?, ?>) o).getKey()) != null &&
|
||||
(v = e.getValue()) != null &&
|
||||
map.remove(k, v));
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterator over the entries of the backing map
|
||||
*/
|
||||
public Iterator<Map.Entry<K, V>> iterator() {
|
||||
return new EntryIterator<K, V>(map);
|
||||
}
|
||||
|
||||
public boolean add(Entry<K, V> e) {
|
||||
return map.putVal(e.getKey(), e.getValue(), false) == null;
|
||||
}
|
||||
|
||||
public boolean addAll(Collection<? extends Entry<K, V>> c) {
|
||||
boolean added = false;
|
||||
for (Entry<K, V> e : c) {
|
||||
if (add(e))
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public final int hashCode() {
|
||||
int h = 0;
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; ) {
|
||||
h += p.hashCode();
|
||||
}
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
public final boolean equals(Object o) {
|
||||
Set<?> c;
|
||||
return ((o instanceof Set) &&
|
||||
((c = (Set<?>) o) == this ||
|
||||
(containsAll(c) && c.containsAll(this))));
|
||||
}
|
||||
|
||||
public Spliterator<Map.Entry<K, V>> spliterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
long n = m.sumCount();
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new EntrySpliterator<K, V>(t, f, 0, f, n < 0L ? 0L : n, m);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super Map.Entry<K, V>> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; )
|
||||
action.accept(new MapEntry<K, V>(p.key, p.val, map));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}.
|
||||
*
|
||||
* @param <K> the element type of the returned set
|
||||
* @return the new set
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <K> KeySetView<K, Boolean> newKeySet() {
|
||||
final SharedHashMapBuilder<Integer, String> builder = SharedHashMapBuilder.of(Integer.class,
|
||||
String.class);
|
||||
|
||||
try {
|
||||
final AbstractVanillaSharedMap chronicleMap = (AbstractVanillaSharedMap) builder.clone().vClass(Boolean.class).file(null)
|
||||
.create();
|
||||
return new KeySetView<K, Boolean>
|
||||
(chronicleMap, Boolean.TRUE);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new {@link Set} backed by a ConcurrentHashMap from the given type to {@code Boolean.TRUE}.
|
||||
*
|
||||
* @param initialCapacity The implementation performs internal sizing to accommodate this many elements.
|
||||
* @param <K> the element type of the returned set
|
||||
* @return the new set
|
||||
* @throws IllegalArgumentException if the initial capacity of elements is negative
|
||||
* @since 1.8
|
||||
*/
|
||||
public static <K> KeySetView<K, Boolean> newKeySet(int initialCapacity) {
|
||||
return newKeySet();
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} view of the keys in this map, using the given common mapped value for any
|
||||
* additions (i.e., {@link Collection#add} and {@link Collection#addAll(Collection)}). This is of course
|
||||
* only appropriate if it is acceptable to use the same value for all additions from this view.
|
||||
*
|
||||
* @param mappedValue the mapped value to use for any additions
|
||||
* @return the set view
|
||||
* @throws NullPointerException if the mappedValue is null
|
||||
*/
|
||||
public KeySetView<K, V> keySet(V mappedValue) {
|
||||
if (mappedValue == null)
|
||||
throw new NullPointerException();
|
||||
return new KeySetView<K, V>(this, mappedValue);
|
||||
}
|
||||
|
||||
/**
|
||||
* A view of a ConcurrentHashMap as a {@link Set} of keys, in which additions may optionally be enabled by
|
||||
* mapping to a common value. This class cannot be directly instantiated. See {@link #keySet() keySet()},
|
||||
* {@link #keySet(Object) keySet(V)}, {@link #newKeySet() newKeySet()}, {@link #newKeySet(int)
|
||||
* newKeySet(int)}.
|
||||
*
|
||||
* @since 1.8
|
||||
*/
|
||||
public static class KeySetView<K, V> extends CollectionView<K, V, K>
|
||||
implements Set<K>, java.io.Serializable, net.openhft.collections.KeySetView<K, V> {
|
||||
private static final long serialVersionUID = 7249069246763182397L;
|
||||
private final V value;
|
||||
|
||||
KeySetView(AbstractVanillaSharedMap<K, V> map, V value) { // non-public
|
||||
super(map);
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the default mapped value for additions, or {@code null} if additions are not supported.
|
||||
*
|
||||
* @return the default mapped value for additions, or {@code null} if not supported
|
||||
*/
|
||||
public V getMappedValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public boolean contains(Object o) {
|
||||
return map.containsKey(o);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the key from this map view, by removing the key (and its corresponding value) from the
|
||||
* backing map. This method does nothing if the key is not in the map.
|
||||
*
|
||||
* @param o the key to be removed from the backing map
|
||||
* @return {@code true} if the backing map contained the specified key
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public boolean remove(Object o) {
|
||||
return map.remove(o) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* @return an iterator over the keys of the backing map
|
||||
*/
|
||||
public Iterator<K> iterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new KeyIterator<K, V>(t, f, 0, f, m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the specified key to this set view by mapping the key to the default mapped value in the
|
||||
* backing map, if defined.
|
||||
*
|
||||
* @param e key to be added
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the specified key is null
|
||||
* @throws UnsupportedOperationException if no default mapped value for additions was provided
|
||||
*/
|
||||
public boolean add(K e) {
|
||||
V v;
|
||||
if ((v = value) == null)
|
||||
throw new UnsupportedOperationException();
|
||||
|
||||
return map.putVal(e, v, true) == null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds all of the elements in the specified collection to this set, as if by calling {@link #add} on
|
||||
* each one.
|
||||
*
|
||||
* @param c the elements to be inserted into this set
|
||||
* @return {@code true} if this set changed as a result of the call
|
||||
* @throws NullPointerException if the collection or any of its elements are {@code null}
|
||||
* @throws UnsupportedOperationException if no default mapped value for additions was provided
|
||||
*/
|
||||
public boolean addAll(Collection<? extends K> c) {
|
||||
boolean added = false;
|
||||
V v;
|
||||
if ((v = value) == null)
|
||||
throw new UnsupportedOperationException();
|
||||
for (K e : c) {
|
||||
if (map.putVal(e, v, true) == null)
|
||||
added = true;
|
||||
}
|
||||
return added;
|
||||
}
|
||||
|
||||
public int hashCode() {
|
||||
int h = 0;
|
||||
for (K e : this)
|
||||
h += e.hashCode();
|
||||
return h;
|
||||
}
|
||||
|
||||
public boolean equals(Object o) {
|
||||
Set<?> c;
|
||||
return ((o instanceof Set) &&
|
||||
((c = (Set<?>) o) == this ||
|
||||
(containsAll(c) && c.containsAll(this))));
|
||||
}
|
||||
|
||||
public Spliterator<K> spliterator() {
|
||||
Node<K, V>[] t;
|
||||
ConcurrentHashMap<K, V> m = map;
|
||||
long n = m.sumCount();
|
||||
int f = (t = m.table) == null ? 0 : t.length;
|
||||
return new KeySpliterator<K, V>(t, f, 0, f, n < 0L ? 0L : n);
|
||||
}
|
||||
|
||||
public void forEach(Consumer<? super K> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = map.table) != null) {
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, t.length, 0, t.length);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; )
|
||||
action.accept(p.key);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} view of the keys contained in this map. The set is backed by the map, so changes
|
||||
* to the map are reflected in the set, and vice-versa. The set supports element removal, which removes
|
||||
* the corresponding mapping from this map, via the {@code Iterator.remove}, {@code Set.remove}, {@code
|
||||
* removeAll}, {@code retainAll}, and {@code clear} operations. It does not support the {@code add} or
|
||||
* {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are <a href="package-summary.html#Weakly"><i>weakly
|
||||
* consistent</i></a>.
|
||||
*
|
||||
* <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT},
|
||||
* and {@link Spliterator#NONNULL}.
|
||||
*
|
||||
* @return the set view
|
||||
*/
|
||||
public AbstractVanillaSharedMap.KeySetView<K, V> keySet() {
|
||||
KeySetView<K, V> ks;
|
||||
return (ks = keySet) != null ? ks : (keySet = new KeySetView<K, V>(this, null));
|
||||
}
|
||||
|
||||
// todo consider a better way to do this so that is is not creating an entry object each time
|
||||
public void forEach(BiConsumer<? super K, ? super V> action) {
|
||||
if (action == null) throw new NullPointerException();
|
||||
|
||||
final EntryIterator entryIterator = new EntryIterator();
|
||||
final EntryIterator entryIterator = new EntryIterator(this);
|
||||
|
||||
for (Entry<K, V> e = entryIterator.next(); entryIterator.hasNext(); e = entryIterator.next()) {
|
||||
action.accept(e.getKey(), e.getValue());
|
||||
@@ -887,8 +1417,6 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
final boolean putReturnsNull;
|
||||
final boolean removeReturnsNull;
|
||||
|
||||
transient Set<Map.Entry<K, V>> entrySet;
|
||||
|
||||
|
||||
public AbstractVanillaSharedMap(SharedHashMapBuilder builder,
|
||||
Class<K> kClass, Class<V> vClass) throws IOException {
|
||||
@@ -1099,7 +1627,7 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
@Override
|
||||
public V put(K key, V value) {
|
||||
super.put(key, value);
|
||||
return put0(key, value, true);
|
||||
return putVal(key, value, true);
|
||||
}
|
||||
|
||||
|
||||
@@ -1108,10 +1636,11 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
*/
|
||||
@Override
|
||||
public V putIfAbsent(K key, V value) {
|
||||
return put0(key, value, false);
|
||||
return putVal(key, value, false);
|
||||
}
|
||||
|
||||
private V put0(K key, V value, boolean replaceIfPresent) {
|
||||
V putVal(K key, V value, boolean replaceIfPresent) {
|
||||
super.putVal(key, value, replaceIfPresent);
|
||||
checkKey(key);
|
||||
checkValue(value);
|
||||
Bytes keyBytes = getKeyAsBytes(key);
|
||||
@@ -1170,6 +1699,7 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
return segments[segmentNum].acquire(keyBytes, key, value, segmentHash, create);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
@@ -1190,15 +1720,45 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
segment.clear();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
* Returns a {@link Collection} view of the values contained in this map. The collection is backed by the
|
||||
* map, so changes to the map are reflected in the collection, and vice-versa. The collection supports
|
||||
* element removal, which removes the corresponding mapping from this map, via the {@code
|
||||
* Iterator.remove}, {@code Collection.remove}, {@code removeAll}, {@code retainAll}, and {@code clear}
|
||||
* operations. It does not support the {@code add} or {@code addAll} operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are <a href="package-summary.html#Weakly"><i>weakly
|
||||
* consistent</i></a>.
|
||||
*
|
||||
* <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT} and {@link
|
||||
* Spliterator#NONNULL}.
|
||||
*
|
||||
* @return the collection view
|
||||
*/
|
||||
@NotNull
|
||||
@Override
|
||||
public Set<Entry<K, V>> entrySet() {
|
||||
return (entrySet != null) ? entrySet : (entrySet = new EntrySet());
|
||||
public Collection<V> values() {
|
||||
ValuesView<K, V> vs;
|
||||
return (vs = values) != null ? vs : (values = new ValuesView<K, V>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a {@link Set} view of the mappings contained in this map. The set is backed by the map, so
|
||||
* changes to the map are reflected in the set, and vice-versa. The set supports element removal, which
|
||||
* removes the corresponding mapping from the map, via the {@code Iterator.remove}, {@code Set.remove},
|
||||
* {@code removeAll}, {@code retainAll}, and {@code clear} operations.
|
||||
*
|
||||
* <p>The view's iterators and spliterators are <a href="package-summary.html#Weakly"><i>weakly
|
||||
* consistent</i></a>.
|
||||
*
|
||||
* <p>The view's {@code spliterator} reports {@link Spliterator#CONCURRENT}, {@link Spliterator#DISTINCT},
|
||||
* and {@link Spliterator#NONNULL}.
|
||||
*
|
||||
* @return the set view
|
||||
*/
|
||||
public Set<Map.Entry<K, V>> entrySet() {
|
||||
EntrySetView<K, V> es;
|
||||
return (es = entrySet) != null ? es : (entrySet = new EntrySetView<K, V>(this));
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
@@ -2139,16 +2699,19 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
}
|
||||
}
|
||||
|
||||
final class EntryIterator implements Iterator<Entry<K, V>>, IntIntMultiMap.EntryConsumer {
|
||||
static final class EntryIterator<K, V> implements Iterator<Entry<K, V>>, IntIntMultiMap.EntryConsumer {
|
||||
|
||||
int segmentIndex = segments.length;
|
||||
private final AbstractVanillaSharedMap map;
|
||||
private int segmentIndex;
|
||||
|
||||
Entry<K, V> nextEntry, lastReturned;
|
||||
|
||||
Deque<Integer> segmentPositions = new ArrayDeque<Integer>(); //todo: replace with a more efficient, auto resizing int[]
|
||||
|
||||
EntryIterator() {
|
||||
EntryIterator(AbstractVanillaSharedMap map) {
|
||||
nextEntry = nextSegmentEntry();
|
||||
this.map = map;
|
||||
segmentIndex = map.segments.length;
|
||||
}
|
||||
|
||||
public boolean hasNext() {
|
||||
@@ -2157,7 +2720,7 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
|
||||
public void remove() {
|
||||
if (lastReturned == null) throw new IllegalStateException();
|
||||
AbstractVanillaSharedMap.this.remove(lastReturned.getKey());
|
||||
map.remove(lastReturned.getKey());
|
||||
lastReturned = null;
|
||||
}
|
||||
|
||||
@@ -2175,17 +2738,17 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
if (segmentPositions.isEmpty()) {
|
||||
switchToNextSegment();
|
||||
} else {
|
||||
final Segment segment = segments[segmentIndex];
|
||||
segment.lock();
|
||||
|
||||
map.segments[segmentIndex].lock();
|
||||
try {
|
||||
while (!segmentPositions.isEmpty()) {
|
||||
Entry<K, V> entry = segment.getEntry(segmentPositions.removeFirst());
|
||||
final Entry<K, V> entry = (Entry<K, V>) map.segments[segmentIndex].getEntry(segmentPositions.removeFirst());
|
||||
if (entry != null) {
|
||||
return entry;
|
||||
}
|
||||
}
|
||||
} finally {
|
||||
segment.unlock();
|
||||
map.segments[segmentIndex].unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2196,12 +2759,12 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
segmentPositions.clear();
|
||||
segmentIndex--;
|
||||
if (segmentIndex >= 0) {
|
||||
final Segment segment = segments[segmentIndex];
|
||||
segment.lock();
|
||||
|
||||
map.segments[segmentIndex].lock();
|
||||
try {
|
||||
segments[segmentIndex].visit(this);
|
||||
map.segments[segmentIndex].visit(this);
|
||||
} finally {
|
||||
segment.unlock();
|
||||
map.segments[segmentIndex].unlock();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2214,7 +2777,7 @@ abstract class AbstractVanillaSharedMap<K, V> extends net.openhft.collections.Co
|
||||
|
||||
final class EntrySet extends AbstractSet<Map.Entry<K, V>> {
|
||||
public Iterator<Map.Entry<K, V>> iterator() {
|
||||
return new EntryIterator();
|
||||
return new EntryIterator(AbstractVanillaSharedMap.this);
|
||||
}
|
||||
|
||||
public boolean contains(Object o) {
|
||||
|
||||
Reference in New Issue
Block a user