先看代码:
import java.util.ArrayList;
import java.util.List;
public class ForeachTest {
public static void main(String[] args) {
List<Integer> test = new ArrayList<>();
for (int i = 0; i < 100; i++) {
test.add(i);
}
System.out.println(test);
for (int i = 0; i < 50; i++) {
for (int t :
test) {
System.out.println(t);
test.remove(t);
break;
}
}
System.out.println(test);
}
}
完整的代码在上面,各位大佬知道为什么会出现那种运行结果吗?如果知道请指点一二,推荐个阅读资料也行,不胜感激。我 Google 了一晚上只找到了一些关于异常的资料,反编译了以后代码是这样的
import java.io.PrintStream;
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class ForeachTest
{
public static void main(String[] paramArrayOfString)
{
ArrayList localArrayList = new ArrayList();
for (int i = 0; i < 100; i++) {
localArrayList.add(Integer.valueOf(i));
}
System.out.println(localArrayList);
for (i = 0; i < 50; i++)
{
Iterator localIterator = localArrayList.iterator();
if (localIterator.hasNext())
{
int j = ((Integer)localIterator.next()).intValue();
System.out.println(j);
localArrayList.remove(j);
}
}
System.out.println(localArrayList);
}
}
我也看不出端倪啊。 我搞明白了会更贴的。
1
shazh520 OP 这个格式我也是醉了,调了四五次才勉强可以看。
|
2
lhx2008 2018-06-22 22:24:59 +08:00
The iterators returned by this class ’ s iterator and listIterator methods are fail-fast: if the list is structurally modified at any time after the iterator is created, in any way except through the iterator ’ s own remove or add methods, the iterator will throw a ConcurrentModificationException. Thus, in the face of concurrent modification, the iterator fails quickly and cleanly, rather than risking arbitrary, non-deterministic behavior at an undetermined time in the future.
from: http://jtuts.com/2016/02/26/remove-element-from-alist-during-iteration-in-java/ |
3
lhx2008 2018-06-22 22:26:38 +08:00
|
5
shazh520 OP 运行结果就像下面这样:
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] 0 1 2 1 2 ...//省略了四十行左右 2 1 2 1 2 [1, 2, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] |
6
zpxshl 2018-06-22 22:29:03 +08:00 via Android
输出结果是什么,我验证下...
|
7
shazh520 OP 不对,上面贴那个运行结果是我后面改过代码的结果。
|
8
shazh520 OP 运行结果是这样(这个绝对没问题):
[0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] 0 1 1 ... 1 1 1 [1, 51, 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91, 92, 93, 94, 95, 96, 97, 98, 99] |
9
hcymk2 2018-06-22 22:35:39 +08:00
for (Integer t : test) {
System.out.println(t); test.remove(t); break; } |
10
zpxshl 2018-06-22 22:38:03 +08:00 via Android
你这代码和反编译代码确定是对应的吗?怎么感觉反编译的代码少了个循环?
|
11
lhx2008 2018-06-22 22:38:29 +08:00
@shazh520 蛋疼,你开始代码太乱没看。
你打断点看下就知道了,remove 不是删除那个元素,而是删除那个下标,所以一直在删除 第 1 个 (从 0 开始)元素,然后你 i 会执行 50 次,就是做了 50 次删除第一个元素。唉,还反编译 |
12
zpxshl 2018-06-22 22:39:50 +08:00 via Android
好吧我错了,少看到个 break...
|
14
lonenol 2018-06-22 22:41:56 +08:00
第一次删了 0,变成 1-99
然后每次都是 remove(1),删第二个元素,保留了 1 就变成你看到的那样了。。 |
15
shazh520 OP @lhx2008 按照这个说法那最后应该是留下了 0 而不是留下 1 没有删除。循环的第一次执行正确的删除了下标为 0 的元素“ 0 ”,但是后面的每次执行为什么就都在删除下标为 1 的元素了呢?
|
16
shazh520 OP @lonenol 我就是搞不明白为啥后面都是删除第二个元素了。 这个太诡异了嘛,没有规律啊。第一次为啥特殊勒,大佬?
|
17
lhx2008 2018-06-22 22:48:10 +08:00 via Android
@shazh520 第一次是 0123,第一个数就是 0,当然就把 0 删掉了,后面变成 123,第一个数是 1,就一直删第一个数,1 是第 0 个数
|
18
zpxshl 2018-06-22 22:48:17 +08:00 via Android 1
@shazh520 你的 list 从 0 开始,第一次循环删掉下标 0,正好值为 0。 list 变成 1 开始。 第二次-n 次循环,每次都是删掉下标为 1 的数,就是删掉 2,3,4,5...
|
19
qusthuang 2018-06-22 22:53:14 +08:00 1
remove(Integer ) 和 remove(int),看下 jdk 实现就知道了
|
20
shazh520 OP @lhx2008 [手动笑哭表情] 大佬,我大体猜到你表达的意思了,你前半句中的第一个数指的是下标 0,后半句中的第一个数指的是下标 1 是吧。 但是我就是想问,为啥第一次删除下标 0,第二次删除下标 1,第三次删除下标 1,...,没规律啊。
|
22
lhx2008 2018-06-22 22:55:26 +08:00 via Android 1
|
25
shazh520 OP 如果代码是这样结果就完全不一样了,就像是 @qusthuang 说的那样,删除对象和下标的问题。
package com.sunhao.seckill; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.boot.test.context.SpringBootTest; import org.springframework.test.context.junit4.SpringRunner; import java.util.ArrayList; import java.util.List; @RunWith(SpringRunner.class) @SpringBootTest public class SeckillApplicationTests { public static void main(String[] args) { List<Integer> integerList = new ArrayList<>(); for (int i = 0; i < 100; i++) { integerList.add(i); } System.out.println(integerList); for (int i = 0; i < 50; i++) { for (Integer integer : integerList) { System.out.println(integer); integerList.remove(integer); break; } } System.out.println(integerList); } } |