ページ

2014年3月13日

javaのiteratorとかiterable


※ とあるところに書いたものの転載です。
※ Java8の話はまた、あとで


こんなコードよく書くよね。


BufferedReader reader = new BufferedReader(new FileReader("myfile.txt"));
String line = null;
while ((line = reader.readLine()) != null) {
     System.out.println(line);
}

まあ、でも、ループの条件式とのとことか、微妙でわかりにくいし、変数のスコープも大きいよね。と言うか、どっかのスクリプト言語みたいに


BufferedReader reader = new BufferedReader(new FileReader("myfile.txt"));
for (String line: reader) {
     System.out.println(line);
}

みたいに書きたくない?
ということで、そこら辺のもの。拡張forループとか言っても、結局iterator使ってグルグルイテレートしているだけ。なんで、イテレートできるようにしてあげたら上みたいな感じで書けるはず。ちなみに、拡張forループ使わずに

for (Iterator iter = reader.iterator(); iter.hasNext();) {
    String line = iter.next();

みたいな書き方は全く嬉しくないので、forループが拡張されたからやりたくなることですね。
さて、実行時にbufferedReaderにメソッドを追加するとかは危険なので今回はBufferedReaderを拡張したIterableReaderを作っちゃいます。

import java.util.*;
import java.io.*;

public class A {
    public static class IterableReader extends BufferedReader implements Iterable {
        public IterableReader(Reader in) {
            super(in);
        }
        public IterableReader(Reader in, int sz) {
            super(in, sz);
        }
        public Iterator iterator() {
            try {
                final String l = readLine();
                return new Iterator() {
                    String last = l;
                    public boolean hasNext() {
                        return last != null;
                    }
   
                    public String next() {
                        String result = last;
                        if (last != null) {
                            try {
                                last = readLine();
                            } catch (IOException e) {
                                throw new RuntimeException(e);
                            }
                        }
                        return result;
                    }

                    public void remove() {
                    }
                };
            } catch (Exception e) {
                throw new RuntimeException(e);
            }
        }
    }

        public static void main(String[] argv) {
        try (IterableReader reader = new IterableReader(new FileReader(argv[0]))) {
            for (String line: reader) {
                System.out.println(line);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
       }

}

Iterableを実装したクラスを作ってあげて、その中でIteratorを返せばいいだけ。ちなみに、無名クラスにもコンストラクタ、書きたい…。
IOExceptionを投げられないので、RuntimeExceptionで代用しているのは許してください。

0 件のコメント: