LoginSignup
5
2

More than 5 years have passed since last update.

今こそStream API入門

Last updated at Posted at 2018-12-16

JJUG CCC 2018 Fallに参加してきました。
@skrb さんの#ccc_g4の講演内容を個人的にまとめました。

Streamってなに?

Streamは単純なイテレータである

  • イテレータは2種類存在する。
    • 外部イテレータ
      • 繰り返しの制御を自分で記述
      • for 拡張for iteratorクラス
      • for文のループ部はもちろん、get(x)の部分も制御部分である。
      • 複雑
      • 記述力はそれほどでもない。
    • 内部イテレータ
      • 繰り返しはライブラリ任せ(Stream API)
      • シンプル
      • 記述力高い。

ラムダ式の立ち位置

蝶のように舞い、鉢のように刺すのがモハメド・アリ
関数のように記述し、クラスのように振る舞うのがラムダ式

関数<============ラムダ式============>クラス
処理             関数のように記述し        状態+処理
               クラスのように振る舞う

Streamはなぜわからないのか?

一度試したけどわからなかった人多数

新しい技術があったら・・・

  • まず使ってみるか?
  • 完全に理解するまで使わないか?

例:オムレツを作るのに、タンパク質の熱変性は60度で、メイラード反応というのがあって・・・
と知ってても、そんなこと気にせず作りますよね??

新しい概念だからこそ、習うより慣れよ。 かけるようになってから仕組みを理解すればよい。

Stream = データの流れ

ループより、加工して処理するものだと考える。
加工するのに、クラス作ったりしたくない。
→ ラムダ式 引数と返り値だけを決めた処理の記述法

(引数)->{
    toDO
    return val;
}

結局Streamはなんなのか

やりたいことをデータの加工という観点で組み立て直す。
工程をシンプル化し、1工程 -> シンプルな4工程にわける -> 最終的にtoList()などで箱詰め。
まずはfor eachからはじめて、徐々にmap->filter等やってみるのが吉

よく使われるラムダ式

1引数 返り値あり Function
1引数 返り値boolean Predicate
1引数 返り値なし Consumer
引数なし 返り値あり Supplier

基本的な書き方

// 基本的なやつ
(String s) -> { return s.length();
// 型は省略可能
(s) -> { return s.length();
// 1行なら returnも省略可能
(s) -> s.length();
// 1引数なら ()も省略可能
s -> s.length();

こんなの覚えなくてもIDEがやってくれる。

最低限覚えておけば良いパターン

  • データを加工する中間の処理。
    • データを取捨選択する
      • filter
      • dropWhile ※1引数 返り値boolean
      • takeWhile
    • データを加工する。
      • map ※1引数 返り値あり
      • flatmap ※1引数 返り値 Stream ←入れ子のstreamとか出てきたときに使う。1次元に変換
    • データを纏める最後の処理。
      • 探す
        • findFirst 単一データの返却
        • findAny 単一データの返却 ※ラムダ式なし
        • anyMatch 正規表現探索
        • allMatch 正規表現探索
        • oneMatch 正規表現探索 ※1引数 返り値 boolean
      • まとめる
        • collect ※Collectors::staticメソッド
        • toList ※ラムダ式なし
        • groupingBy ※1引数 返り値あり(map)
      • 逐次処理
        • for-each 1引数 返り値なし

例: Listから、小文字のaで始まる単語を抜き出す。

example.java
List<String> words = new ArrayList<>() {
    {
        add("apple");
        add("toast");
        add("about");
        add("sun");
    }
};
var results = words.stream()
    .map(word -> word.toLowerCase())
    .filter(word -> word.startsWith("a"))
    .collect(Collectors.toList());
System.out.println(results);

StreamはNull保証されるので、アウトプットの配列のために、new ArrayList()しなくてよい。
Streamでかけないものもあるので無理はしない。

Q&A

Q1. 変換処理部はメソッド参照できるとおもうのですが?
A1. 書けます。しかし、読む人に優しくないので、あまり好ましくない。
Q2. 例外がうまくかけない。ベストプラクティスはあるか
A2. 正解はない。eitherを使うと良い

補足

御本人が、既に発表資料を投稿されていたので、こちらの記事は参考程度に・・・。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2