Abh*_*nav -2 java iteration loops concurrentmodification
我有以下代码:
public static void main(String[] args) {
List<String> input = new ArrayList<>();
List<String> output = new ArrayList<>();
for(int i=0; i< 1000 ;i++){
input.add(i+"");
}
for(int i=0 ; i<input.size(); i++){
String value = input.get(i);
if(Integer.parseInt(value) % 2 == 0){
output.add(value);
input.remove(value);
}
}
input.stream().forEach(System.out::println);
System.out.println("--------------------------------------");
output.stream().forEach(System.out::println);
}
Run Code Online (Sandbox Code Playgroud)
我预计它会抛出,ConcurrentModificationException但它工作正常。有人可以解释一下原因吗?
原因是您在技术上没有迭代列表。相反,您使用递增索引随机访问列表,并删除一些值。如果您更改为这样的代码来迭代列表,它将抛出ConcurrentModificationException
public static void main(String[] args) {\n List<String> input = new ArrayList<>();\n List<String> output = new ArrayList<>();\n for(int i=0; i< 1000 ;i++){\n input.add(i+"");\n }\n \n for (String value : input) {\n if(Integer.parseInt(value) % 2 == 0){\n output.add(value);\n input.remove(value);\n }\n }\n\n input.stream().forEach(System.out::println);\n System.out.println("--------------------------------------");\n output.stream().forEach(System.out::println);\n}\nRun Code Online (Sandbox Code Playgroud)\n与迭代器相比,为什么这可能不是首选方式的后续内容。原因之一是性能。下面是一些使用 JMH 进行测试的基准代码。
\npackage bench;\n\nimport org.openjdk.jmh.annotations.Benchmark;\nimport org.openjdk.jmh.annotations.BenchmarkMode;\nimport org.openjdk.jmh.annotations.Level;\nimport org.openjdk.jmh.annotations.Measurement;\nimport org.openjdk.jmh.annotations.Mode;\nimport org.openjdk.jmh.annotations.OutputTimeUnit;\nimport org.openjdk.jmh.annotations.Param;\nimport org.openjdk.jmh.annotations.Scope;\nimport org.openjdk.jmh.annotations.Setup;\nimport org.openjdk.jmh.annotations.State;\nimport org.openjdk.jmh.annotations.Warmup;\n\nimport java.util.ArrayList;\nimport java.util.Iterator;\nimport java.util.List;\nimport java.util.concurrent.TimeUnit;\n\nimport static java.util.concurrent.TimeUnit.SECONDS;\n\n@State(Scope.Benchmark)\n@BenchmarkMode(Mode.AverageTime)\n@OutputTimeUnit(TimeUnit.MILLISECONDS)\n@Warmup(iterations = 1, time = 3, timeUnit = SECONDS)\n@Measurement(iterations = 3, time = 2, timeUnit = SECONDS)\npublic class JmhBenchmark {\n private List<String> input;\n\n @Param({"100", "1000", "10000"})\n public int length;\n\n @Setup(Level.Invocation)\n public void createInputList() {\n input = new ArrayList<>();\n for (int i = 0; i < length; i++) {\n input.add(i + "");\n }\n }\n\n @Benchmark\n public void iterateWithVariable() {\n for (int i = 0; i < input.size(); i++) {\n String value = input.get(i);\n if (Integer.parseInt(value) % 2 == 0) {\n input.remove(value);\n }\n }\n }\n\n @Benchmark\n public void iterateWithIterator() {\n final Iterator<String> iterator = input.iterator();\n while (iterator.hasNext()) {\n String value = iterator.next();\n if (Integer.parseInt(value) % 2 == 0) {\n iterator.remove();\n }\n }\n }\n\n}\nRun Code Online (Sandbox Code Playgroud)\n我的系统的基准测试结果是
\nBenchmark (length) Mode Cnt Score Error Units\nJmhBenchmark.iterateWithIterator 100 avgt 15 0.002 \xc2\xb1 0.001 ms/op\nJmhBenchmark.iterateWithIterator 1000 avgt 15 0.033 \xc2\xb1 0.001 ms/op\nJmhBenchmark.iterateWithIterator 10000 avgt 15 1.670 \xc2\xb1 0.017 ms/op\nJmhBenchmark.iterateWithVariable 100 avgt 15 0.005 \xc2\xb1 0.001 ms/op\nJmhBenchmark.iterateWithVariable 1000 avgt 15 0.350 \xc2\xb1 0.014 ms/op\nJmhBenchmark.iterateWithVariable 10000 avgt 15 33.591 \xc2\xb1 0.455 ms/op\nRun Code Online (Sandbox Code Playgroud)\n所以我们可以看到使用迭代器从列表中删除一些项目比这个问题提出的方法快很多(>20x)。这是有道理的,您需要在列表中执行随机查找,然后确定是否需要删除它,然后进行另一次查找以查找并删除它。
\n| 归档时间: |
|
| 查看次数: |
91 次 |
| 最近记录: |