java hashmap 通过 hashcode 确定桶位置,用 equals 解决哈希冲突。调用 put 时先计算 key 的 hashcode 找到桶索引,若该桶已有元素则遍历链表或红黑树并用 equals 逐一比对,匹配则覆盖值,否则插入新节点。

HashMap 查找键值对的具体流程
在 get 操作中,同样先计算 hashCode 定位到桶,再使用 equals 方法在桶内寻找匹配的键。如果找到相等的键,返回对应的值;如果遍历完整个桶仍未找到,则返回 null。

import java.util.HashMap;
public class Main {
public static void main(String[] args) {
HashMap<string integer> map = new HashMap();
map.put("apple", 1);
System.out.println(map.get("apple"));
System.out.println(map.get("banana"));
}
}</string>
预期输出: 1 null
自定义对象作为 Key 的注意事项
当使用自定义对象作为 HashMap 的键时,必须同时重写 hashCode 和 equals 方法。如果只重写其中一个,会导致逻辑错误。例如,如果两个对象逻辑上相等(equals 返回 true),但 hashCode 不同,它们会被放入不同的桶中,导致无法通过 get 获取到值。

import java.util.HashMap;
class Person {
String name;
int age;
Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public boolean equals(Object o) {
if (this == o) return true;
if (o == null || getClass() != o.getClass()) return false;
Person person = (Person) o;
return age == person.age && name.equals(person.name);
}
@Override
public int hashCode() {
int result = name.hashCode();
result = 31 * result + age;
return result;
}
}
public class Main {
public static void main(String[] args) {
HashMap<person string> map = new HashMap();
Person p1 = new Person("Alice", 30);
Person p2 = new Person("Alice", 30);
map.put(p1, "Engineer");
System.out.println(map.get(p2));
}
}</person>
预期输出: Engineer
哈希冲突时的处理机制
当两个不同的键计算出相同的 hashCode 时,HashMap 会将其存储在同一个桶中。在 Java 8 之前,HashMap 使用链表来处理冲突。从 Java 8 开始,如果链表的长度超过阈值(默认为 8)且 Map 的大小超过阈值(默认为 64),链表会转换为红黑树,以提高查询效率。这种设计使得在最坏情况下,查找时间复杂度从 O(n) 降低到 O(log n)。
Java免费学习笔记:立即使用
解锁 Java 大师之旅:从入门到精通的终极指南











