Java 而Collections.shuffle()不';t抛出ConcurrentModificationException
实际上,我正在学习集合和异常,我不明白为什么会这样:Java 而Collections.shuffle()不';t抛出ConcurrentModificationException,java,collections,Java,Collections,实际上,我正在学习集合和异常,我不明白为什么会这样: List<Integer> intList = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10)); for (Integer s : intList) { Collections.shuffle(intList); System.out.println(s); } List intList=newarraylist(Array
List<Integer> intList = new ArrayList<Integer>(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
for (Integer s : intList) {
Collections.shuffle(intList);
System.out.println(s);
}
List intList=newarraylist(Arrays.asList(1,2,3,4,5,6,7,8,9,10));
对于(整数s:intList){
集合。洗牌(intList);
系统输出打印项次;
}
在阅读文档时,它指出
此异常可能由检测到并发的方法引发
当不允许修改对象时,对对象进行修改
查看集合的源代码:
public static void shuffle(List<?> list) {
if (r == null) {
r = new Random();
}
shuffle(list, r);
}
publicstaticvoidshuffle(列表){
if(r==null){
r=新随机数();
}
洗牌(列表,r);
}
我来看看洗牌功能:
public static void shuffle(List<?> list, Random rnd) {
int size = list.size();
if (size < SHUFFLE_THRESHOLD || list instanceof RandomAccess) {
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
} else {
Object arr[] = list.toArray();
// Shuffle array
for (int i=size; i>1; i--)
swap(arr, i-1, rnd.nextInt(i));
// Dump array back into list
ListIterator it = list.listIterator();
for (int i=0; i<arr.length; i++) {
it.next();
it.set(arr[i]);
}
}
}
public static void swap(List<?> list, int i, int j) {
final List l = list;
l.set(i, l.set(j, l.get(i)));
}
publicstaticvoidshuffle(列表,随机rnd){
int size=list.size();
if(大小1;i--)
掉期(清单,i-1,rnd.nextInt(i));
}否则{
对象arr[]=list.toArray();
//洗牌阵列
对于(int i=size;i>1;i--)
掉期(arr,i-1,rnd.nextInt(i));
//将数组转储回列表
ListIterator it=list.ListIterator();
对于(int i=0;i而言,答案在于-强调矿山:
(结构修改是添加或删除一个或多个元素,或显式调整支持数组大小的任何操作;仅设置元素的值不是结构修改。)
此类迭代器和listIterator方法返回的迭代器故障快速:如果在创建迭代器后的任何时间以任何方式修改列表,迭代器将抛出ConcurrentModificationException,除非通过迭代器自己的remove或add方法定义后,迭代器将快速、干净地失败,而不是在将来的不确定时间冒任意、不确定行为的风险
shuffle
只调用set
,因此它不执行结构修改,因此迭代器不会抛出异常。答案在于-强调:
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
(结构修改是添加或删除一个或多个元素,或显式调整支持数组大小的任何操作;仅设置元素的值不是结构修改。)
此类迭代器和listIterator方法返回的迭代器故障快速:如果在创建迭代器后的任何时间以任何方式修改列表,迭代器将抛出ConcurrentModificationException,除非通过迭代器自己的remove或add方法定义后,迭代器将快速、干净地失败,而不是在将来的不确定时间冒任意、不确定行为的风险
shuffle
仅调用set
,因此它不执行结构修改,因此迭代器不会引发异常
for (int i=size; i>1; i--)
swap(list, i-1, rnd.nextInt(i));
从本质上讲,这里没有迭代;没有涉及到迭代器
。在第二个分支中,它通过迭代器
进行所有修改,这就是您应该如何避免ConcurrentModificationException的
本质上,这里没有迭代;这里没有涉及到迭代器。在第二个分支中,它通过迭代器进行所有修改,这就是您应该如何做的,以避免ConcurrentModificationException。我认为这里的修改意味着添加(或)删除会改变列表的大小,而不是交换。它可能是特定于实现的,但是set
通常不会更改运行整个ConcurrentModificationException
show的modCount
。我认为这里的修改意味着添加(或)remove会改变列表的大小,而不是SWAP。它可能是特定于实现的,但是set
通常不会更改运行整个ConcurrentModificationException
的modCount
,shuffle
只调用set
-在这个特定的实现中。@Holger:是的,没错。我认为不只是执行交换是一个不寻常的实现。“shuffle
只调用set
”-在这个特定的实现中。@Holger:是的,没错。我认为不只是执行交换是一个不寻常的实现。