【Java】デザインパターンをやってみた 〜 Iterator/ListIterator編 ~

こんにちは。サイオステクノロジーの川田です。

「Iterator」と「ListIterator」のメソッドを使ってみたので、メモとして残していきたいと思います。

Iterator

Iteratorとは?

Iterator(イテレータ)は日本語で「反復子」と翻訳されています。
繰り返し処理の抽象化となります。
要素を順番にアクセスする時に使用するインターフェースです。

抽象化とはどいうことか。
for文でぐるぐる回せばいいのではと思いました。
例えばfor文の場合は具体的に内容を提示する必要があります。
ループカウンタの初期値とか上限回数とか。。

データの要素数なんてわからない!そんなあやふやな場合でも
Iteratorを使えばループで要素を順番に取得することができるのです。

メソッド

メソッドは4つあります。

  • hasNext()

  次の要素がある場合はtrueを返します。

  • next()

  次の要素を返します。

  • remove()

  最後に返された要素を削除します。

  • forEachRemaining()

  各要素ごとに処理を実行します。Java8から追加になっています。

実装してみる

こちらの4つのメソッドを使ってみたいと思います。
「★」をつけている箇所が先ほどのメソッドになります。(3つ)

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

public class Test{
	public static void main(String[] args) {
            List <Integer> list = new ArrayList <>();
            list.add(1);
            list.add(0);
            list.add(5);
            list.add(6);
            Iterator<Integer> it = list.iterator();
            while (it.hasNext()) { //★
                int num = it.next(); //★
                if (num == 0) {
                    // 0は削除
                    it.remove(); //★
                }
            }
            System.out.println(list);
       }
}

numは「1」「0」「5」「6」と順番に処理されていきます。
不要な要素などをコレクションから削除する場合は17行目のように書きます。
こちらの実行結果はこのようになります。

[1, 5, 6]

※next()が呼び出されていない場合や既に remove() を呼び出している場合はエラーになります。

次にforEachRemaining()を実装してみます。

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

public class Test{
	public static void main(String[] args) {
            List <Integer> list = new ArrayList <>();
            list.add(1);
            list.add(0);
            list.add(5);
            list.add(6);
            Iterator<Integer> it = list.iterator();

            it.forEachRemaining(e -> System.out.println(e)); //★
       }
}

Iteartorからの処理を書かなくていいので、ソースがスッキリしますね。
実行結果は以下の通りです。

1
0
5
6

ListIterator

ListIteratorとは?

Iteratorと同じでデータ集合を扱います。先ほどのIteratorとの違いは何なのかとなりますよね。
Iteratorは先頭から順番に処理を行っていましたが、ListIteratorは最後の要素から先頭にも処理が可能です。
逆方向もOKということです!

メソッド

メソッドがいくつかあるので見てみましょう。上3つはIteratorと同じです。

  • hasNext()

  Iteratorと一緒。次の要素がある場合はtrueを返します。

  • next()

  Iteratorと一緒。次の要素を返します。

  • remove()

  Iteratorと一緒。最後に返された要素を削除します。

  • add()

  指定された要素をnext()で返ってきた要素の前に追加します。

  • set()

  データの置き換えをします。

  • hasPrevious()

  逆方向。次の要素がある場合はtrueを返します。

  • previous()

  前の要素を返します。

  • nextIndex()

  次にnext()を呼び出したときに返ってくる要素のインデックス。
  末尾はリストのサイズ。

  • previousIndex()

  次にprevious()を呼び出したときに返ってくる要素のインデックス。
  先頭の場合は「-1」。

実装してみる

★が先ほどのメソッドになります。最初の方はIteratorと使い方が一緒です。
Iteratorから追加されたのが19行目のset()と20行目のadd()になります。

import java.util.ListIterator;
import java.util.List;
import java.util.ArrayList;

public class Test2 {
    public static void main(String[] args) {
        List <Integer> list = new ArrayList <>();
        list.add(1);
        list.add(0);
        list.add(5);
        list.add(6);
        ListIterator<Integer> it = list.listIterator();
        while (it.hasNext()) { //★
            int num = it.next(); //★
            if (num == 0) {
                // 0は削除
                it.remove(); //★
            } else if (num == 6){
                it.set(10); //★
                it.add(11); //★
            }
        }
        it.add(7);
        System.out.println(list);
    }
}

メソッドの説明を基にlistの中身がどのように出力されるか想像してくださいね。
それでは実行結果を表示します!

[1, 5, 10, 11, 7]

removeで0が削除され、setで6→10に置換されています。
その次にaddで11が追加され、最後に7も追加されていることがわかりますね。

nextIndex()とhasPrevious()、previousIndex()も実装してみます。
不要な部分は削除しました。

import java.util.ListIterator;
import java.util.List;
import java.util.ArrayList;

public class Test2 {
    public static void main(String[] args) {
        List <Integer> list = new ArrayList <>();
        list.add(1);
        list.add(0);
        list.add(5);
        list.add(6);
        ListIterator<Integer> it = list.listIterator();
        System.out.println("-----nextIndex");
        while (it.hasNext()) {
            int num = it.next();
            int num2 = it.nextIndex(); //★
            System.out.println(num2);
        }
        System.out.println("-----previousIndex");
        while (it.hasPrevious()) { //★
            int num = it.previous(); //★
            int num2 = it.previousIndex(); //★
            System.out.println(num2);
        }
    }
}

それでは早速実行してみます!

-----nextIndex
1
2
3
4
-----previousIndex
2
1
0
-1

予想は当たりましたか?
previousは逆方向になっていることがわかりますね!

まとめ

いかがでしたでしょうか?IteratorとListIteratorの違い分かりましたか?
今回はこの2つのメソッドを使ってまとめてみました。

ご覧いただきありがとうございます! この投稿はお役に立ちましたか?

役に立った 役に立たなかった

0人がこの投稿は役に立ったと言っています。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です