在本教程中,我们将学习如何在 Java中使用IdentityHashMap类。我们还将研究它与一般的HashMap类有何不同。虽然这个类实现了Map接口,但它违反了Map接口的约定。
IdentityHashMap类。
Java IdentityHashMap类实现了Map接口。Map接口强制要求在键的比较上使用equals()方法。然而,IdentityHashMap类违反了这个契约。相反,它在键的搜索操作上使用引用相等(==)。
在搜索操作中,HashMap使用hashCode()方法进行哈希散列,而IdentityHashMap使用System.identHashCode()方法。它还使用了哈希图的线性探测技术进行搜索操作。
引用相等、System.identityHashCode()和线性探测技术的使用使IdentityHashMap类具有更好的性能。
使用代码:
IdentityHashMap<String, String> identityHashMap = new IdentityHashMap<>(); |
String value = identityHashMap.get(key); |
我们也有不同的方法可用,其工作原理与其他地图对象类似。
- clear(): 删除所有条目
- containsKey(): 查找一个键是否存在于地图中,根据引用是否等同。
- containsValue(): 查找值是否存在于地图中,根据引用是否等同。
- keySet():返回一个基于identity的键集。
- size(): 返回条目的数量
- values():返回一个值的集合
IdentityHashMap并不是线程安全的,和HashMap一样。因此,如果我们有多个线程并行地访问/修改IdentityHashMap条目,我们应该将它们转换为同步map。
我们可以使用Collections类得到一个同步map。
Map<String, String> synchronizedMap = Collections.synchronizedMap(new IdentityHashMap<String, String>()); |
IdentityHashMap在equals()方法上使用引用是否相等(==)来搜索/存储/访问密钥对象。
HashMap<String, String> hashMap = new HashMap<>(identityHashMap); |
当使用一个新的字符串对象 "genre "作为键时,HashMap将其等同于现有的键并更新其值。因此,Map的大小仍然是4。
下面的代码片断显示了IdentityHashMap的不同:
identityHashMap.put(new String("genre"), "Drama"); |
IdentityHashMap认为新的 "genre "字符串对象是一个新的键。
因此,它断定大小为5。两个不同的 "genre "对象被用作两个键。
IdentityHashMap允许可变键。这是该类的另一个有用的特性。
这里我们将把一个简单的Book类作为一个可变的对象。
class Book { |
首先,创建了两个Book类的可变对象。
Book book1 = new Book("A Passage to India", 1924); |
下面是 IdentityHashMap:
IdentityHashMap<Book, String> identityHashMap = new IdentityHashMap<>(10); |
即使键对象被修改,IdentityHashMap也能检索到值。在上面的代码中,assertEquals确保再次检索到相同的文本。由于引用是相等的,这是有可能的。
它对构建特定的框架很有帮助,包括。
- 为一组易变的对象维护代理对象
- 基于一个对象的引用建立一个快速缓存
- 保持一个有引用的对象的内存图