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

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

ただいまの
回答率

90.12%

Iteratorクラスのremoveメソッドの動きが分かりません…

解決済

回答 4

投稿 編集

  • 評価
  • クリップ 1
  • VIEW 3,758

st-access_91s

score 24

※申し訳ありません。仕事都合で回答への返信が大分遅れそうです。。。

以下のコードをコンパイルすると、A,B,D,Eの4つが表示されました。これについて私は、カーソルの関係(要素が繰り上がる)でA,B,Eの3つが表示されるか、スコープの関係(while文で使われているstrとfor文で使われているstrは別スコープ)でA~E全てが表示されるのではないかと考えていたのですが、なぜCだけ削除されたのでしょうか?
Iteratorクラスのremoveメソッドの動きが特殊なのかと調べたのですが、それらしい記述は見つけられませんでした。
ちなみにこのコードは、著書『Java SE7 Silver問題集』の第4章:問18の解説を参考にしたものです。

import java.util.ArrayList;
import java.util.Iterator;

public class Main {
    public static void main(String[] args) {
        ArrayList<String> list = new ArrayList<>();
        list.add("A");
        list.add("B");
        list.add("C");
        list.add("D");
        list.add("E");
        Iterator<String> ite = list.iterator();
        while(ite.hasNext()) {
            String str = ite.next();
            if("C".equals(str)) {
                ite.remove();
            }
        }
        for(String str : list) {
            System.out.println(str);
        }
    }
}

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

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

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

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • swordone

    2016/03/14 00:58

    遅れる理由はいいので、何で引っかかっているのか具体的に説明してください。

    キャンセル

  • st-access_91s

    2016/03/26 20:55

    Iteratorクラスの動きが調べてもよく分からなかったため、removeメソッドの性質やスコープの関係から、A,B,D,Eの4つが表示される理由が分からなかった次第です。皆さんの回答を整理して、段々と理解が進んできている状況です。

    キャンセル

回答 4

+2

Listのメソッドiteratorから生成されるIteratorは、元のListと同じコレクションを参照します。
Iteratorは元のListの要素をnextで順番に取り出し、removeは最後にnextで呼び出した要素を削除する仕組みになっています。
このコードの場合、removeで"C"が削除されたあと、Listは["A", "B", "D", "E"]という状態になり、Iteratorはあえて言うなら"B"と"D"の間にいる状態になります。while文中のstrはIteratorが返した要素を一時的に置いておいているに過ぎません。
その後のfor文で、内部では新たにIteratorが生成されています。もちろん、元のListは["A", "B", "D", "E"]の状態です。内部的にIteratorが取り出した要素がfor文中のstrに置かれ、順次出力しているだけです。

ごく自然な動きだと思うのですが、どこで引っかかっているのでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/26 21:55 編集

    ご回答いただきありがとうございます(返信遅くなって申し訳ありません)。
    カーソルの関係について、著書『Java SE7 Silver問題集』を読み直してみると、removeメソッドの動きとしてでなく拡張for文の要素取り出しの動きとしてカーソルの原理が働いているといった内容が書かれていることに気付きました。swordoneさんの回答を読み、改めてIteratorについて調べて、nextで順番に取り出す際は繰り上がりによる読み飛ばしは発生しないという考えに至りました。
    また、strのスコープに囚われる必要はなく、listの要素が拡張for文処理前段階で"A", "B", "D", "E"になっていることも合点がいきました。
    ちなみに改めて参照したサイトの内、参考にしたのは以下の2つです。

    http://tercel-sakuragaoka.blogspot.jp/2011/06/processing.html
    http://www.javaroad.jp/java_collection5.htm

    キャンセル

checkベストアンサー

0

下記のどちらかで考えていたが、実際は違った。なぜか…ということですね。

カーソルの関係(要素が繰り上がる)でA,B,Eの3つが表示される

スコープの関係(while文で使われているstrとfor文で使われているstrは別スコープ)でA~E全てが表示されるのではないか

どちらの考え方も、プリミティブ型(int,double,booleanなど)と参照型(プリミティブ型以外のすべて)の違いを明確に理解されてないように思います。

Listは参照型ですので、Iteratorに値をコピーしているわけではなく、今Listの何番目を参照しているかという情報を渡しています。

また、IteratorはListを一通り舐めるための栞(しおり)のような役目を果たしています。
今回の場合でいうと、栞が指し示す場所が"C"という文字列であったら、Listの要素を削除するという処理をしています。

たしかに、栞のスコープはListとは違いますが、栞が消えても、Listは残っているので、今回のような結果となります。

答えになっていますでしょうか?

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

0

ArrayListのIteratorなので、ArrayListのremoveが呼ばれます。

Iteratorについては、どういうものなのか、ソースを見ることが出来ます。
自分のPCだと
C:\Program Files\Java\jdk1.7.0_40\src.zip
を回答するとjavaのソースがあります。

Iteratorのソースを見ると remove()が宣言されているだけで
実装がないことがわかります。Interfaceクラスだからです。

Interfaceクラスななんだろう?とか疑問がわいてくれば
それを調べていくのもありです。

楽しんでHackしましょう。

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2016/03/27 03:23

    ご回答いただきありがとうございます(返信遅くなって申し訳ありません)。
    ソースを見てみましたが、Silver未取得者レベルの私にはまだまだ理解が難しいです…。
    でも、もう少し実力がついたら改めてコード読み進めようと思います。

    キャンセル

0

オブジェクト指向のプログラムでは再利用性などを考慮してデザインパターンが用いられることがあります。
JavaでのIteratorインターフェースは、
その「Iteratorパターン」を利用できるようにするためのインターフェースの様です。

自分もまだ勉強中ですが、
デザインパターンについては下記リンク先がとても勉強になります。
TECHSCORE:デザインパターン

Iteratorインターフェースを利用することでカプセル化された状態を維持したまま、
要素を先頭から末尾まで走査するような処理を実現できる様です。

ArrayListがIteratorインターフェースを継承しているので
hasNext()で「次の要素があるか」を確認でき、
next()メソッドで参照する要素を「次へ」移すことが出来ます。
さらに、
(配列、または、)Iterableインターフェースを継承すると拡張for文が利用できます。
拡張for文では配列化されたObjectを一つずつ取り出しながら利用できます。

質問者様のソースでは
while文でIteratorで一旦、走査し、その中で"C"を削除されています。
その後、拡張for文で("C"が削除済みの)listを走査して標準出力されています。

以上、
ご参考になりますでしょうか?

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

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

  • ただいまの回答率 90.12%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる