Loading [MathJax]/jax/input/TeX/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >滚雪球学Java(65-3):详解Java IdentityHashMap的内部实现原理

滚雪球学Java(65-3):详解Java IdentityHashMap的内部实现原理

原创
作者头像
bug菌
发布于 2024-08-04 10:42:52
发布于 2024-08-04 10:42:52
1270
举报
文章被收录于专栏:滚雪球学Java滚雪球学Java

  咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~


🏆本文收录于 **[「滚雪球学Java」 ](https://blog.csdn.net/weixin_43970743/category_9600553.html)专栏,专业攻坚指数级提升,希望能够助你一臂之力,帮你早日登顶实现财富自由🚀;同时,欢迎大家关注&&收藏&&订阅**!持续更新中,up!up!up!!

代码语言:java
AI代码解释
复制
环境说明:Windows 10 + IntelliJ IDEA 2021.3.2 + Jdk 1.8

前言

  Java是一种面向对象的高级编程语言,它具有平台无关性,这意味着Java编译器生成的字节码可以在任何支持Java的平台上运行。Java有许多不同的集合类,包括List、Map、Set等。其中,Map是一个键值对的映射,它允许你使用键来查找值。在Java中,有一个名为IdentityHashMap的独特的Map实现。

摘要

  IdentityHashMap是Java中的一种Map实现,它与其他Map实现不同之处在于,它使用对象的引用作为键的比较方式,而不是使用equals()方法。这意味着,即使两个对象具有相同的值,如果它们的引用不同,它们被认为是不同的键。因此,在IdentityHashMap中,可以将不同的对象作为键存储在Map中。

IdentityHashMap解读

概述

  IdentityHashMap在Java 1.4中被引入,它位于java.util包中。它继承了AbstractMap类并实现了Map接口。在IdentityHashMap中,一个键值对由一个键和一个值组成,其中键是对象的引用,值是任何对象。IdentityHashMap中的键被认为是相同的,当且仅当它们的引用完全相同。这就意味着,即使两个对象的值相同,如果它们的引用不同,它们仍然被视为不同的键。

源代码解析

  IdentityHashMap的源代码可以在Java的官方文档中找到。以下是IdentityHashMap类的部分源码:

代码语言:java
AI代码解释
复制
public class IdentityHashMap<K,V> extends AbstractMap<K,V>
    implements Map<K,V>, java.io.Serializable, Cloneable
{
    // ...
}

  在IdentityHashMap中,键值对被存储在Entry对象中。以下是IdentityHashMap.Entry类的摘要:

代码语言:java
AI代码解释
复制
static class Entry<K,V> extends HashMap.Entry<K,V> {
    Entry(K key, V value) {
        super(key, value);
    }
    public boolean equals(Object o) {
        if (o == this)
            return true;
        if (o instanceof Map.Entry) {
            Map.Entry<?,?> e = (Map.Entry<?,?>)o;
            if (e.getKey() == key)
                return true;
        }
        return false;
    }
    // ...
}

  可以看出,IdentityHashMap.Entry类扩展了HashMap.Entry类。Entry类中的equals()方法比HashMap.Entry类中的equals()方法少了对值的比较,而是只比较键的引用。如果两个Entry对象具有相同的键引用,则认为它们相等。如果两个Entry对象的键引用不同,则认为它们不相等。这使得IdentityHashMap能够将不同的对象作为键存储在Map中。

  如下是部分源码截图:

拓展:

  这是一个静态嵌套类 Entry<K,V>,继承自 HashMap.Entry<K,V>。它有一个带有两个参数的构造函数 Entry(K key, V value),在构造函数中调用父类的构造函数。它还重写了 equals(Object o) 方法,用于在 HashMap 中判断两个 Entry 是否相等。

  在 equals(Object o) 方法中,首先判断传入的对象是否与自身相等,如果相等则返回 true。接着判断传入的对象是否为 Map.Entry 类型,如果是,则将它转换为 Map.Entry<?,?> 类型。最后,判断传入的对象的 key 是否与当前 Entry 的 key 相等,如果相等则返回 true,否则返回 false。

  注意,这里用的是 == 进行判断,因此比较的是 key 的引用是否相等。如果要比较 key 的值是否相等,应该使用 Objects.equals() 方法。

应用场景案例

  IdentityHashMap通常用于需要精确比较对象引用的场景。下面是一个使用IdentityHashMap的简单示例:

代码语言:java
AI代码解释
复制
IdentityHashMap<String, Integer> hashMap = new IdentityHashMap<>();
String s1 = "hello";
String s2 = new String("hello");
hashMap.put(s1, 1);
hashMap.put(s2, 2);
System.out.println(hashMap.size()); // 输出 2

  在这个示例中,我们创建了两个具有相同值的String对象。然后,我们使用这两个String对象作为不同的键将它们添加到IdentityHashMap中。由于IdentityHashMap使用对象的引用比较键,因此它将这两个String对象视为不同的键。因此,IdentityHashMap中有两个键值对。

优缺点分析

优点:

  • 它可以将不同的对象作为键存储在Map中,这使得它非常适合需要精确比较对象引用的场景。
  • 它的实现比其他Map实现更简单,因为它不需要使用equals()方法来比较键。

缺点:

  • IdentityHashMap的性能可能低于其他Map实现。因为它使用对象的引用来比较键,而不是使用equals()方法,所以在查找和插入操作中,它需要更多的处理时间和内存。

类代码方法介绍

构造函数

IdentityHashMap提供了以下构造函数:

代码语言:java
AI代码解释
复制
public IdentityHashMap() // 创建一个空的IdentityHashMap
public IdentityHashMap(int expectedMaxSize) // 创建具有给定初始容量的IdentityHashMap
public IdentityHashMap(Map<? extends K,? extends V> m) // 创建具有与指定Map相同映射关系的IdentityHashMap

方法

  IdentityHashMap继承了AbstractMap类,并实现了Map接口。它提供了许多与其他Map实现相同的方法,例如put()、get()、remove()、size()和clear()等方法。此处只列出IdentityHashMap中与其他Map实现不同的方法:

void putIfAbsent(Object key, Object value)

如果指定的键不与任何值关联,则将它与指定的值关联。否则,不执行任何操作。

拓展:

该代码是Java中Map接口中的putIfAbsent()方法的方法签名。

该方法的作用是:如果指定的键值对(key-value pair)在Map中不存在,则将该键值对插入到Map中,否则不执行任何操作。

方法参数说明:

  • key:要插入的键(key)。
  • value:要插入的值(value)。

方法返回值说明:

  • 如果之前不存在key对应的val,则返回null。
  • 如果之前存在key对应的val,则返回该key对应的旧值。

示例:

代码语言:java
AI代码解释
复制
Map<String, Integer> map = new HashMap<>();
map.put("apple", 1);
map.putIfAbsent("apple", 2);  // 不会执行任何操作,返回1
map.putIfAbsent("banana", 3); // 执行插入操作,返回null
boolean remove(Object key, Object value)

如果指定的键与指定的值相关联,则删除该键值对。否则,不执行任何操作。

拓展:

该方法是用于从映射中移除具有给定键和值的映射(键值对)。

  • 参数:key 表示映射中要移除的键;value 表示映射中要移除的值。
  • 返回值:若映射中存在该键值对,则返回 true,否则返回 false。

示例:

代码语言:java
AI代码解释
复制
Map<String, Integer> map = new HashMap<>();
map.put("A", 10);
map.put("B", 20);
map.put("C", 30);

boolean result1 = map.remove("B", 20); // 移除键为 "B",值为 20 的映射
System.out.println(result1); // 输出 true

boolean result2 = map.remove("D", 40); // 没有键为 "D",值为 40 的映射
System.out.println(result2); // 输出 false

System.out.println(map); // 输出 {A=10, C=30}
Object replace(Object key, Object value)

如果指定的键已经与某个值相关联,则替换该键的值,并返回以前的值。否则,返回null。

拓展:

这个方法是一个Map接口中的方法,用于替换键值对中的旧值。它接收两个参数:要替换的键和新值。如果替换成功,则返回旧值,否则返回null。

以下是方法的详细解释:

参数:

  • key:要替换的键。
  • value:新值。

返回值:

替换成功,返回旧值(老的value);替换失败(该键不存在),返回null。

实现:

实现此方法的类必须实现Map接口。

作用:

用于替换Map中指定键的值。

示例:假设有一个Map对象map,包含键值对 ("a", 1), ("b", 2),现在我们要将键为 "a" 对应的值 1 替换为 10。

代码语言:java
AI代码解释
复制
map.replace("a", 10); // 将键 "a" 的值替换为 10

替换完成后,该map对象的键值对变为:("a", 10), ("b", 2)。此时,replace方法返回值为1,因为替换前 "a" 的值为 1。

boolean replace(Object key, Object oldValue, Object newValue)

如果指定的键已经与指定的旧值相关联,则用指定的新值替换该键的值,并返回true。否则,不执行任何操作。

拓展:

方法名称:replace

参数:Object key,Object oldValue,Object newValue

返回值:boolean

功能描述:根据指定的键(key),替换对应的值(oldValue)为新值(newValue),并返回替换是否成功的布尔值(true表示替换成功,false表示替换失败)。

注意事项:如果Map中不存在指定的键值对,则不进行替换,并返回false。此方法是线程安全的,即使在多个线程同时修改Map中的值也不会出现问题。

测试用例

以下是一个简单的main函数测试用例,它演示了IdentityHashMap的基本用法:

测试结果

代码语言:java
AI代码解释
复制
package com.demo.javase.day65_3;

import java.util.IdentityHashMap;

/**
 * IdentityHashMap示例演示
 *
 * @Author bug菌
 * @Source 公众号:猿圈奇妙屋
 * @Date 2023-11-06 16:53
 */
public class IdentityHashMapTest {

    public static void main(String[] args) {
        IdentityHashMap<String, Integer> hashMap = new IdentityHashMap<>();
        String s1 = "hello";
        String s2 = new String("hello");
        hashMap.put(s1, 1);
        hashMap.put(s2, 2);
        System.out.println(hashMap.get(s1)); // 输出 1
        System.out.println(hashMap.get(s2)); // 输出 2
        System.out.println(hashMap.size()); // 输出 2
        hashMap.remove(s1);
        System.out.println(hashMap.size()); // 输出 1
    }
}

测试结果

  根据如上测试用例,本地测试结果如下,仅供参考,你们也可以自行修改测试用例或者添加更多的测试数据或测试方法,进行熟练学习以此加深理解。

测试代码分析

  根据如上测试用例,在此我给大家进行深入详细的解读一下测试代码,以便于更多的同学能够理解并加深印象。

  该程序演示了IdentityHashMap的使用。在该程序中,创建一个IdentityHashMap对象,其中键的类型为String,值的类型为Integer。然后,将两个键值对添加到IdentityHashMap中,这两个键具有相同的值"hello",但是一个键是使用字符串字面量创建的,另一个键是使用new操作符创建的新字符串。因为这两个键是不同的对象,所以它们在IdentityHashMap中被视为具有不同的身份。

  在输出中,第一个打印语句输出s1的值,即"hello"的值1,第二个打印语句输出s2的值,即也是"hello"的值2。第三个打印语句输出IdentityHashMap的大小,即2,因为其中有两个键值对。最后,使用remove方法从IdentityHashMap中删除s1,并再次输出其大小,这次输出1,因为只剩下包含s2的键值对。

小结

  IdentityHashMap是Java中的一种独特的Map实现。它使用对象的引用作为键的比较方式,而不是使用equals()方法。这意味着,即使两个对象具有相同的值,如果它们的引用不同,它们被认为是不同的键。IdentityHashMap通常用于需要精确比较对象引用的场景。它的实现比其他Map实现更简单,因为它不需要使用equals()方法来比较键。但是,由于它使用对象的引用比较键,而不是使用equals()方法,因此在查找和插入操作中,它需要更多的处理时间和内存。

总结

  IdentityHashMap是Java中的一种独特的Map实现,它使用对象的引用作为键的比较方式。IdentityHashMap通常用于需要精确比较对象引用的场景。它比其他Map实现更简单,因为它不需要使用equals()方法来比较键,但是它的性能可能低于其他Map实现。IdentityHashMap提供了多个与其他Map实现不同的方法,例如putIfAbsent()、remove()、replace()等方法。在使用IdentityHashMap时,需要注意使用对象的引用作为键的比较方式可能会导致一些意外的结果。

☀️建议/推荐你

  无论你是计算机专业的学生,还是对编程有兴趣的小伙伴,都建议直接毫无顾忌的学习此专栏「滚雪球学Java」,bug菌郑重承诺,凡是学习此专栏的同学,均能获取到所需的知识和技能,全网最快速入门Java编程,就像滚雪球一样,越滚越大,指数级提升。

  码字不易,如果这篇文章对你有所帮助,帮忙给bug菌来个一键三连(关注、点赞、收藏) ,您的支持就是我坚持写作分享知识点传播技术的最大动力。   同时也推荐大家关注我的硬核公众号:「猿圈奇妙屋」 ;以第一手学习bug菌的首发干货,不仅能学习更多技术硬货,还可白嫖最新BAT大厂面试真题、4000G Pdf技术书籍、万份简历/PPT模板、技术文章Markdown文档等海量资料,你想要的我都有!

📣关于我

  我是bug菌,CSDN | 掘金 | infoQ | 51CTO 等社区博客专家,历届博客之星Top30,掘金年度人气作者Top40,51CTO年度博主Top12,掘金等平台签约作者,华为云 | 阿里云| 腾讯云等社区优质创作者,全网粉丝合计30w+ ;硬核微信公众号「猿圈奇妙屋」,欢迎你的加入!免费白嫖最新BAT互联网公司面试题、4000G pdf电子书籍、简历模板等海量资料。


--End

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

原创声明:本文系作者授权腾讯云开发者社区发表,未经许可,不得转载。

如有侵权,请联系 cloudcommunity@tencent.com 删除。

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
探索Java中IdentityHashMap的实现与优劣
今天我要给大家分享一些自己日常学习到的一些知识点,并以文字的形式跟大家一起交流,互相学习,一个人虽可以走的更快,但一群人可以走的更远。
喵手
2023/11/17
4130
探索Java中IdentityHashMap的实现与优劣
从代码层读懂HashMap的实现原理
概述  Hashmap继承于AbstractMap,实现了Map、Cloneable、java.io.Serializable接口。它的key、value都可以为null,映射不是有序的。       Hashmap不是同步的,如果想要线程安全的HashMap,可以通过Collections类的静态方法synchronizedMap获得线程安全的HashMap。 Map map = Collections.synchronizedMap(new HashMap()); HashMap 中两个重要
xiangzhihong
2018/02/06
1.4K0
从代码层读懂HashMap的实现原理
深入理解Java中的Map接口:实现原理剖析
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~
bug菌
2024/01/23
5530
深入理解Java中的Map接口:实现原理剖析
【小家java】Java中IdentityHashMap使用详解---允许key重复(阐述和HashMap的区别)
应该有很多人不知道IdentityHashMap的存在,其中不乏工作很多年的Java开发者,会有很多人以为这是第三方jar包,实际上它是Jdk源码自带的集合类。
YourBatman
2019/09/03
3.6K0
Java集合Map接口详解——含源码分析
关于集合中的Collection我们已经讲完了,接下来我们一起来看集合中的另一个大类:Map
秋名山码神
2022/12/13
2390
Java集合Map接口详解——含源码分析
Java HashMap详解及实现原理
Java HashMap是Java集合框架中最常用的实现Map接口的数据结构,它使用哈希表实现,允许null作为键和值,可以存储不同类型的键值对。HashMap提供了高效的存取方法,并且是非线程安全的。在Java中,HashMap被广泛应用于各种场景,如缓存、数据库连接池、路由器等。
程序猿川子
2025/02/17
2050
Java HashMap详解及实现原理
Java当中的集合框架Map
Sunday(星期天)、Monday(星期一)、Tuesday(星期二)、Wednesday(星期三)、Thursday(星期四)、Friday(星期五)、Saturday(星期六)
达达前端
2022/04/29
5230
Java当中的集合框架Map
HashMap 的实现原理
> 1. hashcode 是用来查找的,如果你学过数据结构就应该知道,在查找和排序这一章有
子晋
2022/01/18
3060
白话解析Java中HashMap底层实现原理
再归纳一下就是hashCode是用于查找使用的,而equals是用于比较两个对象的是否相等的。
林老师带你学编程
2019/05/25
6280
Map集合总结
Map集合的key和value都可以是任何引用类型的数据。Map集合的key不允许重复,value允许重复。key和value之间存在单向一对一关系,即通过指定的键可以找到唯一,确定的value。Map集合中获取数据时,只要给出指定的key,就可以取出对应的value。
全栈程序员站长
2022/08/23
5550
Map集合总结
滚雪球学Java(65-1):Java语言中的Hashtable:从入门到精通
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~
bug菌
2024/08/02
1110
滚雪球学Java(65-1):Java语言中的Hashtable:从入门到精通
JAVA--Map集合详解
特点:该集合存储键(key)值(value)对,一对一对往里存,而且要保证键(key)的唯一性。
用户7886150
2021/04/25
6560
滚雪球学Java(65-2):弱引用,强实现:探索Java的WeakHashMap
咦咦咦,各位小可爱,我是你们的好伙伴 bug菌,今天又来给大家手把手教学Java SE系列之集合篇知识点啦,赶紧出来哇,别躲起来啊,听我讲干货记得点点赞,赞多了我就更有动力讲得更欢哦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~
bug菌
2024/08/03
1240
滚雪球学Java(65-2):弱引用,强实现:探索Java的WeakHashMap
Java基础系列(四十五):集合之Map
Map是一个接口,代表的是将键映射到值的对象。一个映射不能包含重复的键,每个键最多只能映射到一个值。
山禾说
2019/01/21
6720
Java之HashMap详解:深入剖析其底层实现与源码分析
咦咦咦,各位小可爱,我是你们的好伙伴——bug菌,今天又来给大家普及Java SE相关知识点了,别躲起来啊,听我讲干货还不快点赞,赞多了我就有动力讲得更嗨啦!所以呀,养成先点赞后阅读的好习惯,别被干货淹没了哦~
bug菌
2024/01/22
6760
Java之HashMap详解:深入剖析其底层实现与源码分析
Java中Map集合常见使用
提要 Map集合概述 Map<K,V> K:键的类型 V:值的类型 把建映射到值的对象中,每一个建最多映射到一个值 不能有重复的键 创建 具体的实现类是:HashMap 用多态的方式创建 //创建Map集合 Map<String, String> hashMap = new HashMap<String, String>(); 添加元素 put() 切记 K 重复会替换之前的值 //创建Map集合 Map<String, String> hashMap = new Hash
用户9006224
2022/12/21
4270
Java中Map集合常见使用
Java 集合框架(6)---- Map 相关类解析(下)
在上上篇文章中,我们看了一下 Java 集合框架中一些 Map 接口下的具体类,主要是对 HashMap 和 TreeMap 实现原理和相关元素操作流程的源码解析。接下来这篇文章中我们继续来解析 Java 集合框架中 Map 接口下的另一些具体类。Ok,话不多说,进入正题,还是先看图:
指点
2019/01/18
7350
Java 集合框架(6)---- Map 相关类解析(下)
JavaSE集合(八)之Map
前面给大家介绍了集合家族中的Collection家族,这一篇给大家分享的是集合中的另一个家族就是Map家族。以前的时候学习Map的时候没有很认真的去学习,我觉得很多东西还是不是很清楚。 这次我将总结的非常详细。程序员的道理里,我们风雨无阻! 一、Map接口 1.1、Map概述   Map 的字面翻译是映射(地图就是一种映射)。将键映射到值的对象,一个映射不能包含重复的键(如果有添加有重复的键,后面的会覆盖掉前面的,但是如果是自定义类型必须重写hashCode()和equals()方法),每个键最多只能映射到
用户1195962
2018/01/18
9890
JavaSE集合(八)之Map
Java集合中的Map接口
  Map是Java三种集合中的一种位于java.util包中,Map作为一个接口存在定义了这种数据结构的一些基础操作,它的最终实现类有很多:HashMap、TreeMap、SortedMap等等,这些最终的子类大多有一个共同的抽象父类AbstractMap。在AbstractMap中实现了大多数Map实现公共的方法。本文介绍Map接口定义了哪些方法,同时JDK8又新增了哪些。
用户1148394
2019/01/07
1.9K0
Java基础-18(01)总结Map,HashMap,HashMap与Hashtable区别,Collections工具类
(1)将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。 (2)Map和Collection的区别? A:Map 存储的是键值对形式的元素,键唯一,值可以重复。夫妻对
Java帮帮
2018/03/15
7580
相关推荐
探索Java中IdentityHashMap的实现与优劣
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档