| `java.util.IdentityHashMap` uses reference equality to compare keys. This is | |
| [in violation of the contract of `java.util.Map`](https://docs.oracle.com/en/java/javase/11/docs/api/java.base/java/util/IdentityHashMap.html), | |
| 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: | |
| 1. An `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`. | |
| 1. `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. | |
| 1. The semantics of `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. | |
| ```java | |
| 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; | |
| } | |
| ``` | |
| ```java | |
| // 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; | |
| } | |
| ``` |