public class IdentityHashMap4D<K,V> extends AbstractMap4D<K,V> implements java.util.Map<K,V>, java.lang.Cloneable
WARNING: This is not a general purpose map. Because it uses System.identityHashCode and ==, instead of hashCode and equals, for comparison, it violated Map's general contract, and may cause undefined behavior when compared to other maps which are not IdentityHashMaps. This is designed only for the rare cases when identity semantics are needed. An example use is topology-preserving graph transformations, such as deep cloning, or as proxy object mapping such as in debugging.
This map permits null
keys and values, and does not
guarantee that elements will stay in the same order over time. The
basic operations (get
and put
) take
constant time, provided System.identityHashCode is decent. You can
tune the behavior by specifying the expected maximum size. As more
elements are added, the map may need to allocate a larger table,
which can be expensive.
This implementation is unsynchronized. If you want multi-thread
access to be consistent, you must synchronize it, perhaps by using
Collections.synchronizedMap(new IdentityHashMap(...));
.
The iterators are fail-fast, meaning that a structural modification
made to the map outside of an iterator's remove method cause the
iterator, and in the case of the entrySet, the Map.Entry, to
fail with a ConcurrentModificationException
.
System.identityHashCode(Object)
,
Collection
,
Map
,
HashMap
,
TreeMap
,
LinkedHashMap
,
WeakHashMap
AbstractMap4D.SimpleEntry<K,V>, AbstractMap4D.SimpleImmutableEntry<K,V>
Constructor and Description |
---|
IdentityHashMap4D()
Create a new IdentityHashMap with the default capacity (21 entries).
|
IdentityHashMap4D(int max)
Create a new IdentityHashMap with the indicated number of
entries.
|
IdentityHashMap4D(java.util.Map<? extends K,? extends V> m)
Create a new IdentityHashMap whose contents are taken from the
given Map.
|
Modifier and Type | Method and Description |
---|---|
void |
clear()
Remove all mappings from this map.
|
java.lang.Object |
clone()
Creates a shallow copy where keys and values are not cloned.
|
boolean |
containsKey(java.lang.Object key)
Tests whether the specified key is in this map.
|
boolean |
containsValue(java.lang.Object value)
Returns true if this HashMap contains the value.
|
java.util.Set<java.util.Map.Entry<K,V>> |
entrySet()
Returns a "set view" of this Map's entries.
|
boolean |
equals(java.lang.Object o)
Compares two maps for equality.
|
V |
get(java.lang.Object key)
Return the value in this Map associated with the supplied key, or
null if the key maps to nothing. |
int |
hashCode()
Returns the hashcode of this map.
|
boolean |
isEmpty()
Returns true if there are no key-value mappings currently in this Map
|
java.util.Set<K> |
keySet()
Returns a "set view" of this Map's keys.
|
V |
put(K key,
V value)
Puts the supplied value into the Map, mapped by the supplied key.
|
void |
putAll(java.util.Map<? extends K,? extends V> m)
Copies all of the mappings from the specified map to this.
|
V |
remove(java.lang.Object key)
Removes from the HashMap and returns the value which is mapped by
the supplied key.
|
int |
size()
Returns the number of kay-value mappings currently in this Map
|
java.util.Collection<V> |
values()
Returns a "collection view" (or "bag view") of this Map's values.
|
equals, hashCode, toString
public IdentityHashMap4D()
public IdentityHashMap4D(int max)
max
- initial sizejava.lang.IllegalArgumentException
- if max is negativepublic void clear()
public java.lang.Object clone()
clone
in class AbstractMap4D<K,V>
Cloneable
,
Object.clone()
public boolean containsKey(java.lang.Object key)
entry == key
instead of
entry == null ? key == null : entry.equals(key)
.containsKey
in interface java.util.Map<K,V>
containsKey
in class AbstractMap4D<K,V>
key
- the key to look forcontainsValue(Object)
,
get(Object)
public boolean containsValue(java.lang.Object value)
entry == value
instead of
entry == null ? value == null : entry.equals(value)
.containsValue
in interface java.util.Map<K,V>
containsValue
in class AbstractMap4D<K,V>
value
- the value to search for in this HashMapcontainsKey(Object)
public java.util.Set<java.util.Map.Entry<K,V>> entrySet()
The semantics of this set, and of its contained entries, are
different from the contract of Set and Map.Entry in order to make
IdentityHashMap work. This means that while you can compare these
objects between IdentityHashMaps, comparing them with regular sets
or entries is likely to have undefined behavior. The entries
in this set are reference-based, rather than the normal object
equality. Therefore, e1.equals(e2)
returns
e1.getKey() == e2.getKey() && e1.getValue() == e2.getValue()
,
and e.hashCode()
returns
System.identityHashCode(e.getKey()) ^
System.identityHashCode(e.getValue())
.
Note that the iterators for all three views, from keySet(), entrySet(), and values(), traverse the Map in the same sequence.
public boolean equals(java.lang.Object o)
this.entrySet().equals(m.entrySet())
as specified by Map,
this will not work with normal maps, since the entry set compares
with == instead of .equals.public V get(java.lang.Object key)
null
if the key maps to nothing.
NOTE: Since the value could also be null, you must use
containsKey to see if this key actually maps to something.
Unlike normal maps, this tests for the key with entry ==
key
instead of entry == null ? key == null :
entry.equals(key)
.
get
in interface java.util.Map<K,V>
get
in class AbstractMap4D<K,V>
key
- the key for which to fetch an associated valueput(Object, Object)
,
containsKey(Object)
public int hashCode()
public boolean isEmpty()
isEmpty
in interface java.util.Map<K,V>
isEmpty
in class AbstractMap4D<K,V>
size() == 0
AbstractMap4D.size()
public java.util.Set<K> keySet()
The semantics of this set are different from the contract of Set in order to make IdentityHashMap work. This means that while you can compare these objects between IdentityHashMaps, comparing them with regular sets is likely to have undefined behavior. The hashCode of the set is the sum of the identity hash codes, instead of the regular hashCodes, and equality is determined by reference instead of by the equals method.
keySet
in interface java.util.Map<K,V>
keySet
in class AbstractMap4D<K,V>
values()
,
entrySet()
public V put(K key, V value)
equals()
this key. NOTE: Since the prior value could also be null, you must
first use containsKey if you want to see if you are replacing the
key's mapping. Unlike normal maps, this tests for the key
with entry == key
instead of
entry == null ? key == null : entry.equals(key)
.put
in interface java.util.Map<K,V>
put
in class AbstractMap4D<K,V>
key
- the key used to locate the valuevalue
- the value to be stored in the HashMapget(Object)
public void putAll(java.util.Map<? extends K,? extends V> m)
putAll
in interface java.util.Map<K,V>
putAll
in class AbstractMap4D<K,V>
m
- the map to copyjava.lang.NullPointerException
- if m is nullAbstractMap4D.put(Object, Object)
public V remove(java.lang.Object key)
null
is returned.
NOTE: Since the value could also be null, you must use
containsKey to see if you are actually removing a mapping.
Unlike normal maps, this tests for the key with entry ==
key
instead of entry == null ? key == null :
entry.equals(key)
.public int size()
public java.util.Collection<V> values()
The semantics of this set are different from the contract of Collection in order to make IdentityHashMap work. This means that while you can compare these objects between IdentityHashMaps, comparing them with regular sets is likely to have undefined behavior. Likewise, contains and remove go by == instead of equals().
values
in interface java.util.Map<K,V>
values
in class AbstractMap4D<K,V>
keySet()
,
entrySet()