質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

Q&A

解決済

3回答

647閲覧

java Listのremoveメソッド

Madai

総合スコア29

Java

Javaは、1995年にサン・マイクロシステムズが開発したプログラミング言語です。表記法はC言語に似ていますが、既存のプログラミング言語の短所を踏まえていちから設計されており、最初からオブジェクト指向性を備えてデザインされています。セキュリティ面が強力であることや、ネットワーク環境での利用に向いていることが特徴です。Javaで作られたソフトウェアは基本的にいかなるプラットフォームでも作動します。

0グッド

1クリップ

投稿2020/01/24 00:59

java

1import java.util.ArrayList; 2 3public class Mail{ 4 public static void main(String[] args){ 5 ArrayList<String> list = new ArrayList<>(); 6 list.add("a"); 7 list.add("i"); 8 list.add("u"); 9 list.add("e"); 10 list.add("o"); 11 for (String str : list){ 12 if("u".equals(str)){ 13 list.remove(str); 14 } 15 } 16 17 for(String str : list){ 18 System.out.println(str); 19 } 20 } 21} 22

上記コードはConcurrentModificationExceptionが発生します。
しかし、下記のコードの場合は同例外が発生しません
どちらも拡張for文での読み出し最中にremoveメソッドを利用していますが、なぜこのような違いが出てくるのでしょうか。

java

1import java.util.ArrayList; 2 3public class Mail{ 4 public static void main(String[] args){ 5 ArrayList<String> list = new ArrayList<>(); 6 list.add("a"); 7 list.add("i"); 8 list.add("u"); 9 list.add("e"); 10 list.add("o"); 11 for (String str : list){ 12 if("u".equals(str)){ 13 list.remove(str); 14 }else{ 15 System.out.println(str); 16 } 17 } 18 } 19} 20

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

quickquip

2020/01/24 01:04

> 下記のコードの場合は同例外が発生しません 発生します(しました)。再確認した方がよいかと。
Madai

2020/01/24 01:08

改めて確認しました。発生しますね お手数をおかけしました。
maisumakun

2020/01/24 01:18

たまたま発生しなかった、ということも考えられます。
guest

回答3

0

自己解決

下記コードにおいても例外が発生しますね
質問を完了とします。

投稿2020/01/24 01:10

Madai

総合スコア29

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

質問の2つのコードは、(現行のJavaのjava.util.ArrayListの実装では)
何度実行しても常にConcurrentModificationExceptionが発生する
と言えます。
実行するたびに結果が違うとか、運次第で発生したりしなかったりするということはありません


ただし、

java

1 for (String str : list){ 2 if("u".equals(str)){ 3 list.remove(str); //★ 4 } 5 }

この部分だけを見て、

★の行が実行されるようなリストを処理した時にConcurrentModificationExceptionが発生するとは限らない

という説明は正しいです。


対照するべきソースは、

java

1 ArrayList<String> list = new ArrayList<>(); 2 list.add("a"); 3 list.add("i"); 4 list.add("u"); 5 list.add("e"); 6 list.add("o"); //違うのはこの行の有無 7 for (String str : list) { 8 if ("u".equals(str)) { 9 list.remove(str); 10 } else { 11 System.out.println(str); 12 } 13 }

java

1 ArrayList<String> list = new ArrayList<>(); 2 list.add("a"); 3 list.add("i"); 4 list.add("u"); 5 list.add("e"); 6 for (String str : list) { 7 if ("u".equals(str)) { 8 list.remove(str); 9 } else { 10 System.out.println(str); 11 } 12 }

です。

前者はConcurrentModificationExceptionが発生し、後者は

a i

という結果になります。

何度実行しても常にそうなります(現行のJavaのjava.util.ArrayListの実装では)。


解説は
https://teratail.com/questions/19288#reply-30118

https://teratail.com/questions/16901#reply-26336
がよいかと。

投稿2020/01/24 01:52

編集2020/01/24 01:57
quickquip

総合スコア11038

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

なぜこのような違いが出てくるのでしょうか。

ConcurrentModificationExceptionが必ず発生することは保証されません

通常、非同期の並行変更がある場合、確かな保証を行うことは不可能なので、イテレータのフェイルファストの動作を保証することはできません。フェイルファスト・イテレータは、ベスト・エフォート・ベースでConcurrentModificationExceptionをスローします。(Java 8より)

なお、ループ内でのリストの個数が変わる変更は、「イテレータ自体のremoveまたはaddメソッド」を使った場合のみ保証されている、とのことです。例外が起きない場合も、正しく動く保証はありません。

投稿2020/01/24 01:14

編集2020/01/24 01:15
maisumakun

総合スコア145184

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問