Javaのはなし
この記事は、 PMOB Advent Calendar 2016 の 12日目 の記事です。
- 前の記事 そうだ俺が怠惰の罪だ - Zodiacの黙示録
- 次の記事 まだないよ
埋め埋め
TL;DR
subListは親のListを参照している
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<String> animals = new ArrayList<>(); animals.add("犬"); animals.add("猫"); animals.add("鳥"); animals.add("人間"); animals.forEach(System.out::println); System.out.println("---"); // List<String> notHuman = animals.subList(0, 2); // -> これは["犬", "猫" ]となる。 List<String> notHuman = animals.subList(0, 3); notHuman.remove(0); animals.forEach(System.out::println); System.out.println("---"); } }
実行結果:
犬 猫 鳥 人間 --- 猫 鳥 人間 ---
下手に操作するとsubListはバグる
以下のコードを実行
import java.util.ArrayList; import java.util.List; public class Main { public static void main(String[] args) { List<String> animals = new ArrayList<>(); animals.add("犬"); animals.add("猫"); animals.add("鳥"); animals.add("人間"); animals.forEach(System.out::println); System.out.println("==="); List<String> notHuman = animals.subList(0, 3); List<String> human = animals.subList(3, 4); notHuman.add("猿"); // ウッキー! System.out.println("- NOT HUMAN"); notHuman.forEach(System.out::println); System.out.println("- HUMAN"); human.forEach(System.out::println); } }
実行結果:
犬 猫 鳥 人間 === - NOT HUMAN 犬 猫 鳥 猿 - HUMAN Exception in thread "main" java.util.ConcurrentModificationException at java.util.ArrayList$SubList.checkForComodification(ArrayList.java:1231) at java.util.ArrayList$SubList.listIterator(ArrayList.java:1091) at java.util.AbstractList.listIterator(AbstractList.java:299) at java.util.ArrayList$SubList.iterator(ArrayList.java:1087) at java.lang.Iterable.forEach(Iterable.java:74) at Main.main(Main.java:26) at sun.reflect.NativeMethodAccessorImpl.invoke0(Native Method) at sun.reflect.NativeMethodAccessorImpl.invoke(NativeMethodAccessorImpl.java:62) at sun.reflect.DelegatingMethodAccessorImpl.invoke(DelegatingMethodAccessorImpl.java:43) at java.lang.reflect.Method.invoke(Method.java:498) at com.intellij.rt.execution.application.AppMain.main(AppMain.java:147)
この例外を見ても僕の頭では難しくて脳が壊れる。
原因
上記記事を見れば大体解決します。
今回の場合「猿」をサブリストに追加したことで親のリストの数が変化した、
ということがhuman
リストに伝える手段が無いために置きたエラーであると解釈できる。
解決
同様の操作をするために参照を切りましょう。
new ArrayList<>(list.subList(from, to));
みたいな。
そもそもsubListをするってことは別に親を参照する必要がない場合のほうが多いのでは?