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:
@@ -1,33 +1,6 @@
|
||||
/*
|
||||
* ORACLE PROPRIETARY/CONFIDENTIAL. Use is subject to license terms.
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*/
|
||||
|
||||
/*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
*
|
||||
* Written by Doug Lea with assistance from members of JCP JSR-166
|
||||
* Expert Group and released to the public domain, as explained at
|
||||
* http://creativecommons.org/publicdomain/zero/1.0/
|
||||
@@ -37,7 +10,6 @@ package net.openhft.collections;
|
||||
|
||||
import net.openhft.lang.io.NativeBytes;
|
||||
|
||||
import java.io.ObjectStreamField;
|
||||
import java.io.Serializable;
|
||||
import java.lang.reflect.Method;
|
||||
import java.lang.reflect.ParameterizedType;
|
||||
@@ -48,7 +20,6 @@ import java.util.concurrent.CountedCompleter;
|
||||
import java.util.concurrent.ForkJoinPool;
|
||||
import java.util.concurrent.atomic.AtomicReference;
|
||||
import java.util.concurrent.locks.LockSupport;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
import java.util.function.*;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
@@ -507,14 +478,7 @@ public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
*/
|
||||
static final int NCPU = Runtime.getRuntime().availableProcessors();
|
||||
|
||||
/**
|
||||
* For serialization compatibility.
|
||||
*/
|
||||
private static final ObjectStreamField[] serialPersistentFields = {
|
||||
new ObjectStreamField("segments", Segment[].class),
|
||||
new ObjectStreamField("segmentMask", Integer.TYPE),
|
||||
new ObjectStreamField("segmentShift", Integer.TYPE)
|
||||
};
|
||||
|
||||
|
||||
/* ---------------- Nodes -------------- */
|
||||
|
||||
@@ -732,48 +696,7 @@ public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
public ConcurrentHashMap() {
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, empty map with an initial table size accommodating the specified number of elements
|
||||
* without the need to dynamically resize.
|
||||
*
|
||||
* @param initialCapacity The implementation performs internal sizing to accommodate this many elements.
|
||||
* @throws IllegalArgumentException if the initial capacity of elements is negative
|
||||
*/
|
||||
public ConcurrentHashMap(int initialCapacity) {
|
||||
if (initialCapacity < 0)
|
||||
throw new IllegalArgumentException();
|
||||
int cap = ((initialCapacity >= (MAXIMUM_CAPACITY >>> 1)) ?
|
||||
MAXIMUM_CAPACITY :
|
||||
tableSizeFor(initialCapacity + (initialCapacity >>> 1) + 1));
|
||||
this.sizeCtl = cap;
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new map with the same mappings as the given map.
|
||||
*
|
||||
* @param m the map
|
||||
*/
|
||||
public ConcurrentHashMap(Map<? extends K, ? extends V> m) {
|
||||
this.sizeCtl = DEFAULT_CAPACITY;
|
||||
putAll(m);
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new, empty map with an initial table size based on the given number of elements ({@code
|
||||
* initialCapacity}) and initial table density ({@code loadFactor}).
|
||||
*
|
||||
* @param initialCapacity the initial capacity. The implementation performs internal sizing to accommodate
|
||||
* this many elements, given the specified load factor.
|
||||
* @param loadFactor the load factor (table density) for establishing the initial table size
|
||||
* @throws IllegalArgumentException if the initial capacity of elements is negative or the load factor is
|
||||
* nonpositive
|
||||
* @since 1.6
|
||||
*/
|
||||
public ConcurrentHashMap(int initialCapacity, float loadFactor) {
|
||||
this(initialCapacity, loadFactor, 1);
|
||||
}
|
||||
|
||||
/**
|
||||
/**
|
||||
* Creates a new, empty map with an initial table size based on the given number of elements ({@code
|
||||
* initialCapacity}), table density ({@code loadFactor}), and number of concurrently updating threads
|
||||
* ({@code concurrencyLevel}).
|
||||
@@ -798,114 +721,12 @@ public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
this.sizeCtl = cap;
|
||||
}
|
||||
|
||||
// Original (since JDK1.2) Map methods
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
public int size() {
|
||||
long n = sumCount();
|
||||
return ((n < 0L) ? 0 :
|
||||
(n > (long) Integer.MAX_VALUE) ? Integer.MAX_VALUE :
|
||||
(int) n);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*/
|
||||
/* public boolean isEmpty() {
|
||||
return sumCount() <= 0L; // ignore transient negative values
|
||||
}*/
|
||||
|
||||
|
||||
/**
|
||||
* Returns the value to which the specified key is mapped, or {@code null} if this map contains no mapping
|
||||
* for the key.
|
||||
*
|
||||
* <p>More formally, if this map contains a mapping from a key {@code k} to a value {@code v} such that
|
||||
* {@code key.equals(k)}, then this method returns {@code v}; otherwise it returns {@code null}. (There
|
||||
* can be at most one such mapping.)
|
||||
*
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public V get(Object key) {
|
||||
Node<K, V>[] tab;
|
||||
Node<K, V> e, p;
|
||||
int n, eh;
|
||||
K ek;
|
||||
int h = spread(key.hashCode());
|
||||
if ((tab = table) != null && (n = tab.length) > 0 &&
|
||||
(e = tabAt(tab, (n - 1) & h)) != null) {
|
||||
if ((eh = e.hash) == h) {
|
||||
if ((ek = e.key) == key || (ek != null && key.equals(ek)))
|
||||
return e.val;
|
||||
} else if (eh < 0)
|
||||
return (p = e.find(h, key)) != null ? p.val : null;
|
||||
while ((e = e.next) != null) {
|
||||
if (e.hash == h &&
|
||||
((ek = e.key) == key || (ek != null && key.equals(ek))))
|
||||
return e.val;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests if the specified object is a key in this table.
|
||||
*
|
||||
* @param key possible key
|
||||
* @return {@code true} if and only if the specified object is a key in this table, as determined by the
|
||||
* {@code equals} method; {@code false} otherwise
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public boolean containsKey(Object key) {
|
||||
return get(key) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns {@code true} if this map maps one or more keys to the specified value. Note: This method may
|
||||
* require a full traversal of the map, and is much slower than method {@code containsKey}.
|
||||
*
|
||||
* @param value value whose presence in this map is to be tested
|
||||
* @return {@code true} if this map maps one or more keys to the specified value
|
||||
* @throws NullPointerException if the specified value is null
|
||||
*/
|
||||
public boolean containsValue(Object value) {
|
||||
if (value == null)
|
||||
throw new NullPointerException();
|
||||
Node<K, V>[] t;
|
||||
if ((t = 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; ) {
|
||||
V v;
|
||||
if ((v = p.val) == value || (v != null && value.equals(v)))
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Maps the specified key to the specified value in this table. Neither the key nor the value can be
|
||||
* null.
|
||||
*
|
||||
* <p>The value can be retrieved by calling the {@code get} method with a key that is equal to the
|
||||
* original key.
|
||||
*
|
||||
* @param key key with which the specified value is to be associated
|
||||
* @param value value to be associated with the specified key
|
||||
* @return the previous value associated with {@code key}, or {@code null} if there was no mapping for
|
||||
* {@code key}
|
||||
* @throws NullPointerException if the specified key or value is null
|
||||
*/
|
||||
public V put(K key, V value) {
|
||||
return putVal(key, value, false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Implementation for put and putIfAbsent
|
||||
*/
|
||||
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;
|
||||
@@ -968,30 +789,9 @@ public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Copies all of the mappings from the specified map to this one. These mappings replace any mappings that
|
||||
* this map had for any of the keys currently in the specified map.
|
||||
*
|
||||
* @param m mappings to be stored in this map
|
||||
*/
|
||||
public void putAll(Map<? extends K, ? extends V> m) {
|
||||
tryPresize(m.size());
|
||||
for (Map.Entry<? extends K, ? extends V> e : m.entrySet())
|
||||
putVal(e.getKey(), e.getValue(), false);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes the key (and its corresponding value) from this map. This method does nothing if the key is not
|
||||
* in the map.
|
||||
*
|
||||
* @param key the key that needs to be removed
|
||||
* @return the previous value associated with {@code key}, or {@code null} if there was no mapping for
|
||||
* {@code key}
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public V remove(Object key) {
|
||||
return replaceNode(key, null, null);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Implementation for the four public remove/replace methods: Replaces node value with v, conditional upon
|
||||
@@ -1068,332 +868,10 @@ public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all of the mappings from this map.
|
||||
*/
|
||||
public void clear() {
|
||||
long delta = 0L; // negative number of deletions
|
||||
int i = 0;
|
||||
Node<K, V>[] tab = table;
|
||||
while (tab != null && i < tab.length) {
|
||||
int fh;
|
||||
Node<K, V> f = tabAt(tab, i);
|
||||
if (f == null)
|
||||
++i;
|
||||
else if ((fh = f.hash) == MOVED) {
|
||||
tab = helpTransfer(tab, f);
|
||||
i = 0; // restart
|
||||
} else {
|
||||
synchronized (f) {
|
||||
if (tabAt(tab, i) == f) {
|
||||
Node<K, V> p = (fh >= 0 ? f :
|
||||
(f instanceof TreeBin) ?
|
||||
((TreeBin<K, V>) f).first : null);
|
||||
while (p != null) {
|
||||
--delta;
|
||||
p = p.next;
|
||||
}
|
||||
setTabAt(tab, i++, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (delta != 0L)
|
||||
addCount(delta, -1);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns the hash code value for this {@link Map}, i.e., the sum of, for each key-value pair in the map,
|
||||
* {@code key.hashCode() ^ value.hashCode()}.
|
||||
*
|
||||
* @return the hash code value for this map
|
||||
*/
|
||||
public int hashCode() {
|
||||
int h = 0;
|
||||
Node<K, V>[] t;
|
||||
if ((t = 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.key.hashCode() ^ p.val.hashCode();
|
||||
}
|
||||
return h;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a string representation of this map. The string representation consists of a list of key-value
|
||||
* mappings (in no particular order) enclosed in braces ("{@code {}}"). Adjacent mappings are separated
|
||||
* by the characters {@code ", "} (comma and space). Each key-value mapping is rendered as the key
|
||||
* followed by an equals sign ("{@code =}") followed by the associated value.
|
||||
*
|
||||
* @return a string representation of this map
|
||||
*/
|
||||
/*public String toString() {
|
||||
Node<K, V>[] t;
|
||||
int f = (t = table) == null ? 0 : t.length;
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, f, 0, f);
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append('{');
|
||||
Node<K, V> p;
|
||||
if ((p = it.advance()) != null) {
|
||||
for (; ; ) {
|
||||
K k = p.key;
|
||||
V v = p.val;
|
||||
sb.append(k == this ? "(this Map)" : k);
|
||||
sb.append('=');
|
||||
sb.append(v == this ? "(this Map)" : v);
|
||||
if ((p = it.advance()) == null)
|
||||
break;
|
||||
sb.append(',').append(' ');
|
||||
}
|
||||
}
|
||||
return sb.append('}').toString();
|
||||
} */
|
||||
|
||||
public String toString() {
|
||||
return super.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Compares the specified object with this map for equality. Returns {@code true} if the given object is a
|
||||
* map with the same mappings as this map. This operation may return misleading results if either map is
|
||||
* concurrently modified during execution of this method.
|
||||
*
|
||||
* @param o object to be compared for equality with this map
|
||||
* @return {@code true} if the specified object is equal to this map
|
||||
*/
|
||||
public boolean equals(Object o) {
|
||||
if (o != this) {
|
||||
if (!(o instanceof Map))
|
||||
return false;
|
||||
Map<?, ?> m = (Map<?, ?>) o;
|
||||
Node<K, V>[] t;
|
||||
int f = (t = table) == null ? 0 : t.length;
|
||||
Traverser<K, V> it = new Traverser<K, V>(t, f, 0, f);
|
||||
for (Node<K, V> p; (p = it.advance()) != null; ) {
|
||||
V val = p.val;
|
||||
Object v = m.get(p.key);
|
||||
if (v == null || (v != val && !v.equals(val)))
|
||||
return false;
|
||||
}
|
||||
for (Map.Entry<?, ?> e : m.entrySet()) {
|
||||
Object mk, mv, v;
|
||||
if ((mk = e.getKey()) == null ||
|
||||
(mv = e.getValue()) == null ||
|
||||
(v = get(mk)) == null ||
|
||||
(mv != v && !mv.equals(v)))
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Stripped-down version of helper class used in previous version, declared for the sake of serialization
|
||||
* compatibility
|
||||
*/
|
||||
static class Segment<K, V> extends ReentrantLock implements Serializable {
|
||||
private static final long serialVersionUID = 2249069246763182397L;
|
||||
final float loadFactor;
|
||||
|
||||
Segment(float lf) {
|
||||
this.loadFactor = lf;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the state of the {@code ConcurrentHashMap} instance to a stream (i.e., serializes it).
|
||||
*
|
||||
* @param s the stream
|
||||
* @throws java.io.IOException if an I/O error occurs
|
||||
* @serialData the key (Object) and value (Object) for each key-value mapping, followed by a null pair.
|
||||
* The key-value mappings are emitted in no particular order.
|
||||
*/
|
||||
private void writeObject(java.io.ObjectOutputStream s)
|
||||
throws java.io.IOException {
|
||||
// For serialization compatibility
|
||||
// Emulate segment calculation from previous version of this class
|
||||
int sshift = 0;
|
||||
int ssize = 1;
|
||||
while (ssize < DEFAULT_CONCURRENCY_LEVEL) {
|
||||
++sshift;
|
||||
ssize <<= 1;
|
||||
}
|
||||
int segmentShift = 32 - sshift;
|
||||
int segmentMask = ssize - 1;
|
||||
@SuppressWarnings("unchecked")
|
||||
Segment<K, V>[] segments = (Segment<K, V>[])
|
||||
new Segment<?, ?>[DEFAULT_CONCURRENCY_LEVEL];
|
||||
for (int i = 0; i < segments.length; ++i)
|
||||
segments[i] = new Segment<K, V>(LOAD_FACTOR);
|
||||
s.putFields().put("segments", segments);
|
||||
s.putFields().put("segmentShift", segmentShift);
|
||||
s.putFields().put("segmentMask", segmentMask);
|
||||
s.writeFields();
|
||||
|
||||
Node<K, V>[] t;
|
||||
if ((t = 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; ) {
|
||||
s.writeObject(p.key);
|
||||
s.writeObject(p.val);
|
||||
}
|
||||
}
|
||||
s.writeObject(null);
|
||||
s.writeObject(null);
|
||||
segments = null; // throw away
|
||||
}
|
||||
|
||||
/**
|
||||
* Reconstitutes the instance from a stream (that is, deserializes it).
|
||||
*
|
||||
* @param s the stream
|
||||
* @throws ClassNotFoundException if the class of a serialized object could not be found
|
||||
* @throws java.io.IOException if an I/O error occurs
|
||||
*/
|
||||
private void readObject(java.io.ObjectInputStream s)
|
||||
throws java.io.IOException, ClassNotFoundException {
|
||||
/*
|
||||
* To improve performance in typical cases, we create nodes
|
||||
* while reading, then place in table once size is known.
|
||||
* However, we must also validate uniqueness and deal with
|
||||
* overpopulated bins while doing so, which requires
|
||||
* specialized versions of putVal mechanics.
|
||||
*/
|
||||
sizeCtl = -1; // force exclusion for table construction
|
||||
s.defaultReadObject();
|
||||
long size = 0L;
|
||||
Node<K, V> p = null;
|
||||
for (; ; ) {
|
||||
@SuppressWarnings("unchecked")
|
||||
K k = (K) s.readObject();
|
||||
@SuppressWarnings("unchecked")
|
||||
V v = (V) s.readObject();
|
||||
if (k != null && v != null) {
|
||||
p = new Node<K, V>(spread(k.hashCode()), k, v, p);
|
||||
++size;
|
||||
} else
|
||||
break;
|
||||
}
|
||||
if (size == 0L)
|
||||
sizeCtl = 0;
|
||||
else {
|
||||
int n;
|
||||
if (size >= (long) (MAXIMUM_CAPACITY >>> 1))
|
||||
n = MAXIMUM_CAPACITY;
|
||||
else {
|
||||
int sz = (int) size;
|
||||
n = tableSizeFor(sz + (sz >>> 1) + 1);
|
||||
}
|
||||
@SuppressWarnings("unchecked")
|
||||
Node<K, V>[] tab = (Node<K, V>[]) new Node<?, ?>[n];
|
||||
int mask = n - 1;
|
||||
long added = 0L;
|
||||
while (p != null) {
|
||||
boolean insertAtFront;
|
||||
Node<K, V> next = p.next, first;
|
||||
int h = p.hash, j = h & mask;
|
||||
if ((first = tabAt(tab, j)) == null)
|
||||
insertAtFront = true;
|
||||
else {
|
||||
K k = p.key;
|
||||
if (first.hash < 0) {
|
||||
TreeBin<K, V> t = (TreeBin<K, V>) first;
|
||||
if (t.putTreeVal(h, k, p.val) == null)
|
||||
++added;
|
||||
insertAtFront = false;
|
||||
} else {
|
||||
int binCount = 0;
|
||||
insertAtFront = true;
|
||||
Node<K, V> q;
|
||||
K qk;
|
||||
for (q = first; q != null; q = q.next) {
|
||||
if (q.hash == h &&
|
||||
((qk = q.key) == k ||
|
||||
(qk != null && k.equals(qk)))) {
|
||||
insertAtFront = false;
|
||||
break;
|
||||
}
|
||||
++binCount;
|
||||
}
|
||||
if (insertAtFront && binCount >= TREEIFY_THRESHOLD) {
|
||||
insertAtFront = false;
|
||||
++added;
|
||||
p.next = first;
|
||||
TreeNode<K, V> hd = null, tl = null;
|
||||
for (q = p; q != null; q = q.next) {
|
||||
TreeNode<K, V> t = new TreeNode<K, V>
|
||||
(q.hash, q.key, q.val, null, null);
|
||||
if ((t.prev = tl) == null)
|
||||
hd = t;
|
||||
else
|
||||
tl.next = t;
|
||||
tl = t;
|
||||
}
|
||||
setTabAt(tab, j, new TreeBin<K, V>(hd));
|
||||
}
|
||||
}
|
||||
}
|
||||
if (insertAtFront) {
|
||||
++added;
|
||||
p.next = first;
|
||||
setTabAt(tab, j, p);
|
||||
}
|
||||
p = next;
|
||||
}
|
||||
table = tab;
|
||||
sizeCtl = n - (n >>> 2);
|
||||
baseCount = added;
|
||||
}
|
||||
}
|
||||
|
||||
// ConcurrentMap methods
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the previous value associated with the specified key, or {@code null} if there was no mapping
|
||||
* for the key
|
||||
* @throws NullPointerException if the specified key or value is null
|
||||
*/
|
||||
public V putIfAbsent(K key, V value) {
|
||||
return putVal(key, value, true);
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws NullPointerException if the specified key is null
|
||||
*/
|
||||
public boolean remove(Object key, Object value) {
|
||||
if (key == null)
|
||||
throw new NullPointerException();
|
||||
return value != null && replaceNode(key, null, value) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @throws NullPointerException if any of the arguments are null
|
||||
*/
|
||||
public boolean replace(K key, V oldValue, V newValue) {
|
||||
if (key == null || oldValue == null || newValue == null)
|
||||
throw new NullPointerException();
|
||||
return replaceNode(key, newValue, oldValue) != null;
|
||||
}
|
||||
|
||||
/**
|
||||
* {@inheritDoc}
|
||||
*
|
||||
* @return the previous value associated with the specified key, or {@code null} if there was no mapping
|
||||
* for the key
|
||||
* @throws NullPointerException if the specified key or value is null
|
||||
*/
|
||||
public V replace(K key, V value) {
|
||||
if (key == null || value == null)
|
||||
throw new NullPointerException();
|
||||
return replaceNode(key, value, null);
|
||||
}
|
||||
|
||||
// Overrides of JDK8+ Map extension method defaults
|
||||
|
||||
@@ -1498,48 +976,7 @@ public abstract class ConcurrentHashMap<K, V> extends AbstractMap<K, V>
|
||||
}
|
||||
|
||||
|
||||
// Hashtable legacy methods
|
||||
|
||||
/**
|
||||
* Legacy method testing if some key maps into the specified value in this table. This method is
|
||||
* identical in functionality to {@link #containsValue(Object)}, and exists solely to ensure full
|
||||
* compatibility with class {@link java.util.Hashtable}, which supported this method prior to introduction
|
||||
* of the Java Collections framework.
|
||||
*
|
||||
* @param value a value to search for
|
||||
* @return {@code true} if and only if some key maps to the {@code value} argument in this table as
|
||||
* determined by the {@code equals} method; {@code false} otherwise
|
||||
* @throws NullPointerException if the specified value is null
|
||||
*/
|
||||
public boolean contains(Object value) {
|
||||
return containsValue(value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the keys in this table.
|
||||
*
|
||||
* @return an enumeration of the keys in this table
|
||||
* @see #keySet()
|
||||
*/
|
||||
public Enumeration<K> keys() {
|
||||
Node<K, V>[] t;
|
||||
int f = (t = table) == null ? 0 : t.length;
|
||||
return new KeyIterator<K, V>(t, f, 0, f, this);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns an enumeration of the values in this table.
|
||||
*
|
||||
* @return an enumeration of the values in this table
|
||||
* @see #values()
|
||||
*/
|
||||
public Enumeration<V> elements() {
|
||||
Node<K, V>[] t;
|
||||
int f = (t = table) == null ? 0 : t.length;
|
||||
return new ValueIterator<K, V>(t, f, 0, f, this);
|
||||
}
|
||||
|
||||
// ConcurrentHashMap-only methods
|
||||
|
||||
/**
|
||||
* Returns the number of mappings. This method should be used instead of {@link #size} because a
|
||||
|
||||
Reference in New Issue
Block a user