java.util.IdentityHashMap
uses reference equality to compare keys. This is
in violation of the contract of java.util.Map
,
which states that object equality (the keys’ equals
methods) should be used
for key comparison. This peculiarity can lead to confusion and subtle bugs,
especially when the two types of maps are used together. This check attempts to
reduce confusion between these two very different kinds of maps in a few ways:
IdentityHashMap
’s reference-equality behavior would be surprising if
its declared type was java.util.Map
. The type of an IdentityHashMap
is
required to be explicit, i.e., IdentityHashMap
should not be upcast to
Map
.IdentityHashMap
’s equals
method will only compare equal to a Map
if
the keys of both are the same instances. This makes little sense for an
object-equality map, so IdentityHashMap.equals()
should only be used to
compare to other IdentityHashMap
s.Map
and IdentityHashMap
are different enough that they
should be considered different, incompatible types. Converting one to the
other is discouraged, as it is often a mistake.Map<String, String> bad(Map<String, String> aMap, IdentityHashMap<String, String> identityMap) {
// Don't assign an `IdentityHashMap` to a plain `Map`-typed variable
Map<String, String> myMap = identityMap;
// Don't use `IdentityHashMap`'s `equals` method with a `Map`
identityMap.equals(aMap);
// Don't convert between `IdentityHashMap` and `Map`
identityMap.putAll(aMap);
identityMap = new IdentityHashMap<>(aMap);
return identityMap;
}
// Keep `IdentityHashMap`'s type information around so maintainers know when
// reference equality is being used.
IdentityHashMap<String, String> good() {
IdentityHashMap<String, String> identityMap = new IdentityHashMap<>();
// ...
return identityMap;
}
Suppress false positives by adding the suppression annotation @SuppressWarnings("IdentityHashMapUsage")
to the enclosing element.