順を追ってイテレーションからラムダ式、ストリームAPIまでを理解

0)最初は昔の書き方

まずList型の場合、繰り返し処理は
for (int i = 0; i < string_list.size(); i++) {
    String str = string_list.get(i)
    System.out.println(str);
}
って書くけど、この書き方はもう古い

 

1)まずはイテレーション

ずばりイテレータを使ってこう書く
for(Iterator<String> i = string_list.iterator(); i.hasNext();){
    String str=(String)i.next();
    System.out.println(str);
}

 

2)ジェネリックスを使ってみる

さらにジェネリックスを使うとキャストしなくてよくなって
for(Iterator i = string_list.iterator(); i.hasNext();){
    String str = i.next()
    System.out.println(str);
}
となる。

 

3)拡張forを使ってみる

さらに拡張forを使うと
for(String str : string_list){
    System.out.println(str);
}
と書けるとのこと。なるほど!少し楽!

このように、イテレータを取得して、操作して、イテレータを実行するような処理を「外部イテレータ」と言うらしい。
ここで終わりではなく、さらに覚えなくてはいけないのが...
・内部イテレータ
ラムダ式
・Stream API

 

4)外部イテレータから内部イテレータに書き換え

上記外部イテレータを内部イテレータに書き換えるとforEachを使って
string_list.forEach(
    new Cunsumer<String>(){
        public void accept(String str){
            System.out.println(str);
        }
    }
);
となるらしい。なんか長いし難しい... 
これだと並列処理とかもできたりするみたいけど、もう少しすっきりしないだろうか?

 

5)ラムダ式を使ってみる

上記の内部イテレータを、ラムダ式を使って書くと
string_list.forEach(
str -> {
    System.out.println(str);
});
となるとのこと。なんかすっきりした!

1行だと{}を省略して
string_list.forEach(str -> System.out.println(str));
でも可!

ラムダ式の本体を省略して、メソッド参照なんかを使うと
string_list.forEach(System.out::println);
まで省略できるとか。

色々省略しすぎて逆に良く分からなくなってきた。

 

6)最後にStream API

上記のラムダ式をStream APIを使って書くと
string_list.stream().forEach(str -> {
    System.out.println(str);
});
となるらしい。

Stream APIは中間操作と終端操作というのがあって、
string_list.stream()
    .filter(str -> str.length <= 5)
    .forEach(str -> System.out.println(str));
みたいに書くと5文字以下のstrだけSystem.outするみたいなこともできるっぽい!便利!

中間操作と終端操作は色々種類があるから、使いこなせれば記述もすっきりして便利だけど、馴染みのない人にはフルにラムダ式やStream APIまで使いこなしているコードは理解するのにも一苦労しそう。

 

最後)まとめ

単純なfor(...){}から始まり → 0)
Iteratorを使うようになり → 1)
ジェネリックスで型変換を省略するようになり → 2)
拡張forで記述を省略し → 3)
外部イテレータから内部イテレータになり → 4)
ラムダ式になり、 → 5)
最後はStream APIになる。 → 6)


順を追っていくといろいろ進化してるんだな。。。