行业资讯 2025年08月6日
0 收藏 0 点赞 813 浏览 4589 个字
摘要 :

文章目录 1.IdentityHashMap简介 2.使用IdentityHashMap 2.1 创建IdentityHashMap 2.2 IdentityHashMap方法 2.3 IdentityHashMap示例 3.HashMap和IdentityHashMap之间……




  • 1.IdentityHashMap简介
  • 2.使用IdentityHashMap
    • 2.1 创建IdentityHashMap
    • 2.2 IdentityHashMap方法
    • 2.3 IdentityHashMap示例
  • 3.HashMap和IdentityHashMap之间的区别
    • 3.1 引用相等性
    • 3.2 可变键
  • 4.IdentityHashMap用途
  • 5.结论

在本教程中,我们将详细探讨Java的IdentityHashMap,并突出显示IdentityHashMap与HashMap之间的区别。

IdentityHashMap在比较键(或值)时使用引用相等性而不是对象相等性。换句话说,在IdentityHashMap中,两个键k1和k2仅当(k1==k2)时才被视为相等。您可以在IdentityHashMap中使用可变键,因为引用相等性不会随对象状态的改变而改变。

1.IdentityHashMap简介

IdentityHashMap类位于java.util包中,是Map接口的基于HashTable的实现,自Java版本1.4以来一直存在。

  • 该类不是通用的Map实现。虽然它实现了Map接口,但在对象比较时它违反了Map的一般契约,它使用引用相等性(==)来搜索Map中的键。这个类仅在需要引用相等性的情况下使用。
  • IdentityHashMap在内部使用System.identityHashCode()方法来计算
  • IdentityHashMap几乎具有与HashMap相同的特性,包括构造函数和方法。但就性能而言,与HashMap相比,它在使用HashTable的线性探测技术而不是HashMap使用的链接技术时提供更好的性能。
  • 它的迭代器在尝试在迭代期间修改Map时会抛出ConcurrentModificationException。
  • 它不是一个线程安全的类。使用Collections.synchronizedMap()来获得该类的线程安全引用。

在Java集合中,该类的声明如下:

public class IdentityHashMap<K, V> extends AbstractMap<K, V> implements Map<K, V>, Serializable, Cloneable

如上所示,它实现了Map接口并扩展了AbstractMap类。

2.使用IdentityHashMap

2.1 创建IdentityHashMap

我们可以通过使用以下构造函数来创建IdentityHashMap:

  • IdentityHashMap():用于创建具有初始默认容量21的空映射。
  • IdentityHashMap(int initialCapacity):用于创建具有给定初始容量的空映射。
  • IdentityHashMap(Map m):用于创建具有与指定Map相同条目的新IdentityHashMap。
IdentityHashMap<String, String> map = new IdentityHashMap<>();
IdentityHashMap<String, String> map = new IdentityHashMap<>(16);
Map<String, String> map = new HashMap<String, String>() {{
    put(\"key1\", \"value1\");
   put(\"key2\", \"value2\");
}};
IdentityHashMap<String, String> map = new IdentityHashMap<>(map);

2.2 IdentityHashMap方法

该类中包含的一些经常使用的方法包括:

  • Object put(key, value):将键-值对插入映射中。
  • Object get(key):返回映射中指定键的值。
  • boolean containsKey(key):根据指定键是否在映射中找到,返回true或false。
  • boolean containsValue(value):类似于containsKey()方法,它查找指定值而不是键。
  • Set keySet():返回映射中存储的所有键的集合。
  • Set entrySet():返回映射中存储的所有映射的集合。
  • Value remove(Object key):移除指定键的键-值对。
  • int size():返回映射的大小,即存储在映射中的键-值对数量。

2.3 IdentityHashMap示例

让我们快速介绍如何创建其实例以及如何使用上述方法的示例。

//创建 IdentityHashMap
IdentityHashMap<Integer, String> map = new IdentityHashMap<>();
//用put()新增值
map.put(1, \"A\");
map.put(2, \"B\");
map.put(3, \"C\");
System.out.println(map);
//获取值
String value = map.get(2);
System.out.println(value);
//判断key是否存在
System.out.println(map.containsKey(3));
System.out.println(map.containsValue(\"Z\"));
//根据key移除一个键值对
map.remove(3);
System.out.println(map);
//map长度
System.out.println(map.size());
//遍历map
for(Map.Entry<Integer, String> entry : map.entrySet())
{
    System.out.println(entry.getKey() + \" :: \" + entry.getValue());
}

请注意,IdentityHashMap支持null键和值。

IdentityHashMap<String, String> map = new IdentityHashMap<>();
map.put(null, \"Some Value\");   //Null key 
map.put(\"Some Key\", null);      //Null value

3.HashMap和IdentityHashMap之间的区别

3.1 引用相等性

IdentityHashMap在比较键(和值)时使用引用相等性(==)而不是Map的equals()方法。让我们通过一个示例来理解。

//内存中有两个相似但不同的实例
Integer key1 = new Integer(10);
Integer key2 = new Integer(10);
//IdentityHashMap中的相同key
IdentityHashMap<Integer, String> identityHashMap = new IdentityHashMap<>();
identityHashMap.put(key1, \"India\");
identityHashMap.put(key2, \"USA\");
System.out.println(\"Identity HashMap : \" + identityHashMap);
// HashMap中的相同key
HashMap<Integer, String> hashMap = new HashMap<>();
hashMap.put(key1, \"India\");
hashMap.put(key2, \"USA\");
System.out.println(\"HashMap : \" + hashMap);

注意程序输出:

Identity HashMap : {10=USA, 10=India}
HashMap : {10=USA}

HashMap拒绝了第二个键,因为它使用equals()方法来比较键,而对于两个键,值都是10。IdentityHashMap使用引用相等性,因此两个键分别存储在内存中,因此它们的引用是不相等的。

当我们将键值对放入HashMap时,它会更新先前的条目,我们会得到一个存储在映射中的单个条目。

3.2 可变键

我们可以在IdentityHashMap中使用可变键,而对于HashMap,始终建议使用不可变键。

让我们通过一个示例来理解,并创建一个可变类“Vehicle”。定义必要的访问器方法,hashCode()和equals()方法。

class Vehicle {
  private String name;
  private int year;
  public Vehicle(String name, int year) {
    this.name = name;
    this.year = year;
  }
  //Getters and Setters
  @Override
  public String toString() {
    return \"Vehicle{\" +
        \"vehicleName=\'\" + name + \'\\\'\' +
        \", modelYear=\" + year +
        \'}\';
  }
  @Override
  public boolean equals(Object o) {
    if (this == o) return true;
    if (o == null || getClass() != o.getClass()) return false;
    Vehicle vehicle = (Vehicle) o;
    if (Objects.equals(year, vehicle.year)) return false;
    return Objects.equals(name, vehicle.name);
  }
  @Override
  public int hashCode() {
    int result = name != null ? name.hashCode() : 0;
    result = 31 * result + year;
    return result;
  }
}

我们将向映射中添加一些键值对,然后更改键和值的状态。然后,我们将使用更改后的键检索条目,应该返回原始值。

Vehicle vehicle = new Vehicle(\"Honda\", 2015);
Map<Vehicle, String> identityHashMap1 = new IdentityHashMap<>();
identityHashMap1.put(vehicle, \"Old Vehicle\");
// 改变key状态
vehicle.setName(\"Modified Vehicle\");
vehicle.setYear(2022);
// 从map中获取vehicle的value
System.out.println( identityHashMap1.get(vehicle) );   //输出 \'Old Vehicle\'

4.IdentityHashMap用途

IdentityHashMap在罕见的用例中使用,我们在使用这个类时必须小心。

  • 它有助于构建特定的框架,包括:
  • Spring bean或Singleton类型,因为它们精确管理某些类型的一个实例
  • 维护一组可变对象的代理对象
  • 类对象,因为它们也可以通过引用进行比较
  • 基于对象引用的缓存实例
  • 保持具有引用的对象的内存图

5.结论

我们了解了Java中的IdentityHashMap,它的内部工作方式以及它与HashMap之间的区别。我们还涵盖了涉及HashMap和IdentityHashMap的实际示例以及它们在键比较方面的不同行为。

微信扫一扫

支付宝扫一扫

版权: 转载请注明出处:https://www.zuozi.net/9370.html

管理员

相关推荐
2025-08-06

文章目录 一、Reader 接口概述 1.1 什么是 Reader 接口? 1.2 Reader 与 InputStream 的区别 1.3 …

988
2025-08-06

文章目录 一、事件溯源 (一)核心概念 (二)Kafka与Golang的优势 (三)完整代码实现 二、命令…

465
2025-08-06

文章目录 一、证明GC期间执行native函数的线程仍在运行 二、native线程操作Java对象的影响及处理方…

348
2025-08-06

文章目录 一、事务基础概念 二、MyBatis事务管理机制 (一)JDBC原生事务管理(JdbcTransaction)…

456
2025-08-06

文章目录 一、SnowFlake算法核心原理 二、SnowFlake算法工作流程详解 三、SnowFlake算法的Java代码…

517
2025-08-06

文章目录 一、本地Jar包的加载操作 二、本地Class的加载方法 三、远程Jar包的加载方式 你知道Groo…

832
发表评论
暂无评论

还没有评论呢,快来抢沙发~

助力内容变现

将您的收入提升到一个新的水平

点击联系客服

在线时间:08:00-23:00

客服QQ

122325244

客服电话

400-888-8888

客服邮箱

122325244@qq.com

扫描二维码

关注微信客服号