Java-HashMap详解

位置:首页>文章>详情   分类: Java教程 > 编程技术   阅读(434)   2024-03-28 16:21:52

HashMap 基于哈希算法工作,根据 Java 文档 HashMap 有以下四个构造函数,

HashMap​()

HashMap​(int initialCapacity)

HashMap​(int initialCapacity, float loadFactor)

HashMap​(Map<? extends K,? extends V> m)

构造函数 描述
构造一个具有默认初始容量 (16) 和默认加载因子 (0.75) 的空 HashMap
构造一个具有指定初始容量和默认加载因子 (0.75) 的空 HashMap
构造一个具有指定初始容量和加载因子的空 HashMap
构造一个新的 HashMap,其映射与指定的 Map 相同。

让我们编写简单的 java 程序,检查 Map 内部是如何工作的

  1. 创建一个简单的 Map 并向其添加一个键和一个值
public static void main(String[] args) {

Map<Integer, String> map = new HashMap<>();

map.put(1, "Java");

}

我们刚刚创建了 Simple Map,它以 Integer 为键,以 String 为值,并添加了“1”作为 Key 和“Java”作为值。通过使用 eclipse 调试功能,让我们看看Map里面有什么

它创建了 16 个块(0-15)并插入了第一个块,键为整数“1”,值为字符串“Java”。请检查红色框,其余所有框都用 null 初始化。

2.将第二个键和值添加到同一个映射

public static void main(String[] args) {

Map<Integer, String> map = new HashMap<>();

map.put(1, "Java");

map.put(2, "Angular");

}

让我们再次在 Eclipse 调试中查看Map

现在映射包含两个键 (1,2) 和两个值(“Java”、“Angular”),正如预期的那样,但是键分别准确地添加在第一个块和第二个块中,为什么?

因为我们知道 Map 基于哈希算法工作,每当我们将键插入映射时,它会调用 Object#hashcode() 方法,根据 hashCode() 的值,它会将键插入到该块中。

在上面的例子中,Integer 类用它的原始 int 值覆盖了 hashCode,这就是为什么 (1,java) 存储在第一个块中而 (2,Angular) 存储在第二个块中的原因。

3.让我们用我们自己的类做同样的实验

创建一个简单的 Employee 类,如下所示

private static class Employee{
int id;
String name;

Employee(int id, String name){
this.id = id;
this.name = name;
}
}

使用此类作为Map的 Key 并以相同的方式检查

public static void main(String[] args) {
Map<Employee, String> map = new HashMap<>(10);
map.put(new Employee(1, "Ramesh"), "Java");
map.put(new Employee(2, "Sathish"), "Angular");
}

我们添加了两个键作为 Employee 对象和值作为字符串,让我们看看这次键存储在哪个块中

这次,它存储在第 8 个块和第 14 个块中(为什么?简单的答案是因为 Employee 对象的 hashCode),为了确认这一点,让将 Employee 的 hashCode() 重写为常量值并检查映射。如果我们的分析正确,它必须将所有密钥存储在同一个块中。

相应地更新 Employee 类

private static class Employee{
int id;
String name;
Employee(int id, String name){
this.id = id;
this.name = name;
}
@Override
public int hashCode() {
return 10;
}
}

我们不需要对Map进行任何更改,现在让我们看看密钥存储在哪里

是的,只有第 10 个方块被两个物体填满,为什么?因为两个员工对象都返回了相同的 hashCode(即 10)。但是 Map 如何识别这两个对象不是重复的呢?我们在内部知道 Map#Key 是一个 entrySet(java.util.Set) 它调用 equals 方法来验证键是否重复。

在从 Map 中检索值的同时,首先它会检查给定键的 hashCode,并根据它转到该块,在找到该块后,它将调用 equals() 以获得确切的值。

因此,将 hashCode() 覆盖为常量根本不值得推荐。并且当我们覆盖 hashCode() 时,我们不应该忘记也覆盖 equals() 方法(即 hashCode()/equals() 契约)。

标签2: Java教程
地址:https://www.cundage.com/article/jcg-java-hashmap-detail-explanation.html

相关阅读

Java HashSet 教程展示了如何使用 Java HashSet 集合。 Java哈希集 HashSet 是一个不包含重复元素的集合。此类为基本操作(添加、删除、包含和大小)提供恒定时间性...
SpringApplicationBuilder 教程展示了如何使用 SpringApplicationBuilder 创建一个简单的 Spring Boot 应用程序。 春天 是用于创建企业应...
通道是继 buffers 之后 java.nio 的第二个主要新增内容,我们在之前的教程中已经详细了解了这一点。通道提供与 I/O 服务的直接连接。 通道是一种在字节缓冲区和通道另一端的实体(通...
课程大纲 Elasticsearch 是一个基于 Lucene 的搜索引擎。它提供了一个分布式的、支持多租户的全文搜索引擎,带有 HTTP Web 界面和无模式的 JSON 文档。 Elasti...
解析器是强大的工具,使用 ANTLR 可以编写可用于多种不同语言的各种解析器。 在这个完整的教程中,我们将: 解释基础:什么是解析器,它可以用来做什么 查看如何设置 ANTLR 以便在 Java...
Java 是用于开发各种桌面应用程序、Web 应用程序和移动应用程序的最流行的编程语言之一。以下文章将帮助您快速熟悉 Java 语言,并迈向 API 和云开发等更复杂的概念。 1. Java语言...
Java中的继承是指子类继承或获取父类的所有非私有属性和行为的能力。继承是面向对象编程的四大支柱之一,用于提高层次结构中类之间的代码可重用性。 在本教程中,我们将了解 Java 支持的继承类型,...
Java Message Service 是一种支持正式通信的 API,称为 网络上计算机之间的消息传递。 JMS 为支持 Java 程序的标准消息协议和消息服务提供了一个通用接口。 JMS 提...
Java 项目中的一项常见任务是将日期格式化或解析为字符串,反之亦然。解析日期意味着你有一个代表日期的字符串,例如“2017-08-3”,你想把它转换成一个代表 Java 中日期的对象,例如Ja...
之前,我介绍了spring 3 + hibernate 集成 示例和struts 2 hello world 示例。在本教程中,我将讨论在将 spring 框架与 struts 与 hibern...