Methods Summary |
---|
public void | clear()Removes all elements from this map, leaving it empty.
size = 0;
for (int i = 0; i < elementData.length; i++) {
elementData[i] = null;
}
modCount++;
|
public java.lang.Object | clone()Returns a new IdentityHashMap with the same mappings and size as this
one.
try {
return super.clone();
} catch (CloneNotSupportedException e) {
return null;
}
|
private int | computeElementArraySize()
return (int) (((long) threshold * 10000) / loadFactor) * 2;
|
private void | computeMaxSize()
threshold = (int) ((long) (elementData.length / 2) * loadFactor / 10000);
|
public boolean | containsKey(java.lang.Object key)Returns whether this map contains the specified key.
if (key == null) {
key = NULL_OBJECT;
}
int index = findIndex(key, elementData);
return elementData[index] == key;
|
public boolean | containsValue(java.lang.Object value)Returns whether this map contains the specified value.
if (value == null) {
value = NULL_OBJECT;
}
for (int i = 1; i < elementData.length; i = i + 2) {
if (elementData[i] == value) {
return true;
}
}
return false;
|
public java.util.Set | entrySet()Returns a set containing all of the mappings in this map. Each mapping is
an instance of {@link Map.Entry}. As the set is backed by this map,
changes in one will be reflected in the other.
return new IdentityHashMapEntrySet<K, V>(this);
|
public boolean | equals(java.lang.Object object)Compares this map with other objects. This map is equal to another map is
it represents the same set of mappings. With this map, two mappings are
the same if both the key and the value are equal by reference. When
compared with a map that is not an IdentityHashMap, the equals method is
neither necessarily symmetric (a.equals(b) implies b.equals(a)) nor
transitive (a.equals(b) and b.equals(c) implies a.equals(c)).
/*
* We need to override the equals method in AbstractMap because
* AbstractMap.equals will call ((Map) object).entrySet().contains() to
* determine equality of the entries, so it will defer to the argument
* for comparison, meaning that reference-based comparison will not take
* place. We must ensure that all comparison is implemented by methods
* in this class (or in one of our inner classes) for reference-based
* comparison to take place.
*/
if (this == object) {
return true;
}
if (object instanceof Map) {
Map<?, ?> map = (Map) object;
if (size() != map.size()) {
return false;
}
Set<Map.Entry<K, V>> set = entrySet();
// ensure we use the equals method of the set created by "this"
return set.equals(map.entrySet());
}
return false;
|
private int | findIndex(java.lang.Object key, java.lang.Object[] array)
int length = array.length;
int index = getModuloHash(key, length);
int last = (index + length - 2) % length;
while (index != last) {
if (array[index] == key || (array[index] == null)) {
/*
* Found the key, or the next empty spot (which means key is not
* in the table)
*/
break;
}
index = (index + 2) % length;
}
return index;
|
public V | get(java.lang.Object key)Returns the value of the mapping with the specified key.
if (key == null) {
key = NULL_OBJECT;
}
int index = findIndex(key, elementData);
if (elementData[index] == key) {
Object result = elementData[index + 1];
return massageValue(result);
}
return null;
|
private java.util.IdentityHashMap$IdentityHashMapEntry | getEntry(java.lang.Object key)
if (key == null) {
key = NULL_OBJECT;
}
int index = findIndex(key, elementData);
if (elementData[index] == key) {
return getEntry(index);
}
return null;
|
private java.util.IdentityHashMap$IdentityHashMapEntry | getEntry(int index)
Object key = elementData[index];
Object value = elementData[index + 1];
if (key == NULL_OBJECT) {
key = null;
}
if (value == NULL_OBJECT) {
value = null;
}
return new IdentityHashMapEntry<K, V>((K) key, (V) value);
|
private int | getModuloHash(java.lang.Object key, int length)
return ((System.identityHashCode(key) & 0x7FFFFFFF) % (length / 2)) * 2;
|
private int | getThreshold(int maxSize)
// assign the threshold to maxSize initially, this will change to a
// higher value if rehashing occurs.
return maxSize > 3 ? maxSize : 3;
|
public boolean | isEmpty()Returns whether this IdentityHashMap has no elements.
return size == 0;
|
public java.util.Set | keySet()Returns a set of the keys contained in this map. The set is backed by
this map so changes to one are reflected by the other. The set does not
support adding.
if (keySet == null) {
keySet = new AbstractSet<K>() {
@Override
public boolean contains(Object object) {
return containsKey(object);
}
@Override
public int size() {
return IdentityHashMap.this.size();
}
@Override
public void clear() {
IdentityHashMap.this.clear();
}
@Override
public boolean remove(Object key) {
if (containsKey(key)) {
IdentityHashMap.this.remove(key);
return true;
}
return false;
}
@Override
public Iterator<K> iterator() {
return new IdentityHashMapIterator<K, K, V>(
new MapEntry.Type<K, K, V>() {
public K get(MapEntry<K, V> entry) {
return entry.key;
}
}, IdentityHashMap.this);
}
};
}
return keySet;
|
private V | massageValue(java.lang.Object value)
return (V) ((value == NULL_OBJECT) ? null : value);
|
private java.lang.Object[] | newElementArray(int s)
return new Object[s];
|
public V | put(K key, V value)Maps the specified key to the specified value.
Object _key = key;
Object _value = value;
if (_key == null) {
_key = NULL_OBJECT;
}
if (_value == null) {
_value = NULL_OBJECT;
}
int index = findIndex(_key, elementData);
// if the key doesn't exist in the table
if (elementData[index] != _key) {
modCount++;
if (++size > threshold) {
rehash();
index = findIndex(_key, elementData);
}
// insert the key and assign the value to null initially
elementData[index] = _key;
elementData[index + 1] = null;
}
// insert value to where it needs to go, return the old value
Object result = elementData[index + 1];
elementData[index + 1] = _value;
return massageValue(result);
|
public void | putAll(java.util.Map map)Copies all the mappings in the specified map to this map. These mappings
will replace all mappings that this map had for any of the keys currently
in the given map.
putAllImpl(map);
|
private void | putAllImpl(java.util.Map map)
if (map.entrySet() != null) {
super.putAll(map);
}
|
private void | readObject(java.io.ObjectInputStream stream)
stream.defaultReadObject();
int savedSize = stream.readInt();
threshold = getThreshold(DEFAULT_MAX_SIZE);
elementData = newElementArray(computeElementArraySize());
for (int i = savedSize; --i >= 0;) {
K key = (K) stream.readObject();
put(key, (V) stream.readObject());
}
size = savedSize;
|
private void | rehash()
int newlength = elementData.length << 1;
if (newlength == 0) {
newlength = 1;
}
Object[] newData = newElementArray(newlength);
for (int i = 0; i < elementData.length; i = i + 2) {
Object key = elementData[i];
if (key != null) {
// if not empty
int index = findIndex(key, newData);
newData[index] = key;
newData[index + 1] = elementData[i + 1];
}
}
elementData = newData;
computeMaxSize();
|
public V | remove(java.lang.Object key)Removes the mapping with the specified key from this map.
if (key == null) {
key = NULL_OBJECT;
}
boolean hashedOk;
int index, next, hash;
Object result, object;
index = next = findIndex(key, elementData);
if (elementData[index] != key) {
return null;
}
// store the value for this key
result = elementData[index + 1];
// shift the following elements up if needed
// until we reach an empty spot
int length = elementData.length;
while (true) {
next = (next + 2) % length;
object = elementData[next];
if (object == null) {
break;
}
hash = getModuloHash(object, length);
hashedOk = hash > index;
if (next < index) {
hashedOk = hashedOk || (hash <= next);
} else {
hashedOk = hashedOk && (hash <= next);
}
if (!hashedOk) {
elementData[index] = object;
elementData[index + 1] = elementData[next + 1];
index = next;
}
}
size--;
modCount++;
// clear both the key and the value
elementData[index] = null;
elementData[index + 1] = null;
return massageValue(result);
|
public int | size()Returns the number of mappings in this IdentityHashMap.
return size;
|
public java.util.Collection | values()Returns a collection of the values contained in this map. The collection
is backed by this map so changes to one are reflected by the other. The
collection supports remove, removeAll, retainAll and clear operations,
and it does not support add or addAll operations.
This method returns a collection which is the subclass of
AbstractCollection. The iterator method of this subclass returns a
"wrapper object" over the iterator of map's entrySet(). The {@code size}
method wraps the map's size method and the {@code contains} method wraps
the map's containsValue method.
The collection is created when this method is called for the first time
and returned in response to all subsequent calls. This method may return
different collections when multiple concurrent calls occur, since no
synchronization is performed.
if (valuesCollection == null) {
valuesCollection = new AbstractCollection<V>() {
@Override
public boolean contains(Object object) {
return containsValue(object);
}
@Override
public int size() {
return IdentityHashMap.this.size();
}
@Override
public void clear() {
IdentityHashMap.this.clear();
}
@Override
public Iterator<V> iterator() {
return new IdentityHashMapIterator<V, K, V>(
new MapEntry.Type<V, K, V>() {
public V get(MapEntry<K, V> entry) {
return entry.value;
}
}, IdentityHashMap.this);
}
@Override
public boolean remove(Object object) {
Iterator<?> it = iterator();
while (it.hasNext()) {
if (object == it.next()) {
it.remove();
return true;
}
}
return false;
}
};
}
return valuesCollection;
|
private void | writeObject(java.io.ObjectOutputStream stream)
stream.defaultWriteObject();
stream.writeInt(size);
Iterator<?> iterator = entrySet().iterator();
while (iterator.hasNext()) {
MapEntry<?, ?> entry = (MapEntry) iterator.next();
stream.writeObject(entry.key);
stream.writeObject(entry.value);
}
|