1136 字
3 分钟
Java集合核心问题:哈希冲突与并发修改异常

哈希冲突#

在哈希表中,哈希冲突指的是不同的键(Key)在经过哈希函数计算后,得到的哈希值相同的情况。哈希冲突的解决是哈希表实现中的一个重要问题。

解决哈希冲突的常用方法包括链地址法(Separate Chaining)和开放地址法(Open Addressing)等。在解决哈希冲突时,除了依赖于哈希值的计算外,还需要依赖于键的 equals 方法和 hashCode 方法。

  1. equals 方法equals 方法是用来比较两个对象是否相等的方法。在哈希表中,当发生哈希冲突时,需要通过 equals 方法来判断两个键是否相等。如果两个键通过 equals 方法比较相等,则它们被认为是同一个键,此时可能需要进行后续的操作,比如更新值或者插入到链表中等。

  2. hashCode 方法hashCode 方法是用来计算对象的哈希值的方法。在哈希表中,哈希值被用作为键的索引,用于确定键在哈希表中的存储位置。当哈希冲突发生时,需要通过 hashCode 方法来计算键的哈希值,并据此确定键的存储位置。

在 Java 中,当我们自定义类作为键存储在哈希表中时,通常需要重写 equals 方法和 hashCode 方法,以确保对象在逻辑上相等(根据业务需求自定义相等的标准),并且具有相同的哈希值。这样可以保证哈希表在使用自定义类作为键时能够正确地处理哈希冲突。

  • equals相等,hashCode一定相等

  • hashCode相等,equals不一定相等

HashMap put流程

HashMap resize流程

为什么迭代器删除元素不会有并发修改异常?#

迭代器删除元素时不会引发并发修改异常的原因是因为迭代器的 remove 方法是在迭代器内部对集合进行修改的一种安全方式。它通过迭代器本身来进行操作,确保了在删除元素时不会导致并发修改异常。

在迭代器的实现中,迭代器内部会维护一个称为 “expectedModCount” 的计数器,该计数器表示创建迭代器时集合的修改次数。当你使用迭代器的 remove 方法删除元素时,它会检查 “expectedModCount” 是否与实际的修改次数(“modCount”)相匹配。如果相匹配,说明在迭代过程中没有其他线程对集合进行修改,删除操作是合法的,不会引发并发修改异常。

如果在迭代器使用过程中集合发生了结构性修改(例如,通过集合的其他方法进行了添加或删除操作),“modCount” 会增加,而 “expectedModCount” 保持不变。此时,当你尝试使用迭代器的 remove 方法时,它会检测到这个不一致,抛出 ConcurrentModificationException 异常,以提示发生了并发修改。

总之,迭代器的 remove 方法通过内部维护的计数器来确保在安全的情况下对集合进行修改,以防止并发修改异常。这种机制是为了在多线程环境中提供一些基本的安全性,尽管在并发编程中,还需要额外的同步手段来确保线程安全。

避免ConcurrentModificationException#

使用迭代器来遍历,并且使用迭代器来删除

是的,确切地说,如果在使用迭代器遍历集合的同时需要对集合进行修改,应该使用迭代器的 remove 方法而不是集合的 remove 方法。这是因为迭代器的 remove 方法是集合修改的安全方式,它不会导致 ConcurrentModificationException 异常。

以下是一个示例,演示了使用迭代器遍历并删除元素的正确方式:

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class IteratorExample {
public static void main(String[] args) {
List<String> list = new ArrayList<>();
list.add("One");
list.add("Two");
list.add("Three");
Iterator<String> iterator = list.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println(element);
// 使用迭代器的 remove 方法安全地删除元素
if (element.equals("Two")) {
iterator.remove();
}
}
System.out.println("List after removal: " + list);
}
}

在这个例子中,通过使用迭代器的 remove 方法,我们可以在遍历过程中安全地删除元素而不会导致并发修改异常。在集合的迭代器模式中,这是一种常见的做法,以确保在遍历过程中修改集合时不会破坏迭代器的状态。

延伸阅读#

分享

如果这篇文章对你有帮助,欢迎分享给更多人!

Java集合核心问题:哈希冲突与并发修改异常
https://onecodemaker.cn/posts/java核心-02-集合/
作者
糖糖IT
发布于
2026-01-09
许可协议
CC BY-NC-SA 4.0

部分信息可能已经过时

目录