[英]Why does this code NOT throw a ConcurrentModificationException?
I'm trying to understand why some of my code doesn't throw a ConcurrentModificationException.我试图理解为什么我的一些代码不会抛出 ConcurrentModificationException。 I am looping through elements of a Set and then adding more elements to the set, but I expected an exception.我循环遍历 Set 的元素,然后向该集合添加更多元素,但我预计会出现异常。
Problem: Given a directed tree, return true if two given nodes have a common ancestor.问题:给定一棵有向树,如果两个给定的节点有一个共同的祖先,则返回 true。 Note this is not a rooted tree (ie a tree with one root).请注意,这不是一棵有根的树(即只有一个根的树)。 We are given edge pairs that are (parent, child).我们得到的边对是(父母,孩子)。 Nodes have unique IDs.节点具有唯一的 ID。
import java.io.*;
import java.util.*;
class Solution {
public static void main(String[] args) {
int[][] pairs = {{11,6},{9,6},{9,8},{10,8}, {6,2},{5,2},{5,1},{8,3},{8,4}};
System.out.println(hasCommonAncestor(pairs, 3,4));
System.out.println(hasCommonAncestor(pairs, 2,4));
System.out.println(hasCommonAncestor(pairs, 1,3));
System.out.println(hasCommonAncestor(pairs, 6,8));
}
private static boolean hasCommonAncestor(int[][] pairs, int a, int b) {
Map<Integer, Set<Integer>> firstLevelParents = new HashMap<>();
for(int[] pair : pairs) {
int parent = pair[0];
int child = pair[1];
Set<Integer> parents = firstLevelParents.getOrDefault(child, new HashSet<>());
parents.add(parent);
firstLevelParents.put(child, parents);
}
Set<Integer> aParents = firstLevelParents.get(a);
Set<Integer> bParents = firstLevelParents.get(b);
for(Integer parent : aParents) {
Set<Integer> parentsParents = firstLevelParents.getOrDefault(parent, new HashSet<>());
aParents.addAll(parentsParents);
}
for(Integer parent : bParents) {
Set<Integer> parentsParents = firstLevelParents.getOrDefault(parent, new HashSet<>());
bParents.addAll(parentsParents);
}
return aParents.removeAll(bParents);
}
}
This code may still throw a ConcurrentModificationException
under certain inputs.此代码可能仍会在某些输入下引发ConcurrentModificationException
。 From the Javadoc for the exception:来自 Javadoc 的异常:
Note that fail-fast behavior cannot be guaranteed as it is, generally speaking, impossible to make any hard guarantees in the presence of unsynchronized concurrent modification.请注意,不能保证快速失败行为,因为一般来说,在存在非同步并发修改的情况下不可能做出任何硬保证。 Fail-fast operations throw ConcurrentModificationException on a best-effort basis.快速失败操作会尽最大努力抛出 ConcurrentModificationException。 Therefore, it would be wrong to write a program that depended on this exception for its correctness: ConcurrentModificationException should be used only to detect bugs.因此,编写一个依赖此异常来确保其正确性的程序是错误的: ConcurrentModificationException 应该仅用于检测错误。
As an example, this code works fine:例如,此代码工作正常:
public final class Main {
public static void main(String[] args) {
Set<Integer> numbers = new HashSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
for (Integer n : numbers) {
numbers.add(n + 1);
}
System.out.println(numbers); // [1, 2, 3, 4]
}
}
But this will throw a ConcurrentModificationException
:但这会抛出ConcurrentModificationException
:
public final class Main {
public static void main(String[] args) {
Set<Integer> numbers = new HashSet<>();
numbers.add(1);
numbers.add(2);
numbers.add(3);
for (Integer n : numbers) {
// Changed 1 to a 10.
numbers.add(n + 10);
}
System.out.println(numbers);
}
}
In other words, some paths of your code may lead to a ConcurrentModificationException
but others may not and you should not depend on this result.换句话说,您的代码的某些路径可能会导致ConcurrentModificationException
但其他路径可能不会,您不应该依赖此结果。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.