StreamAPIについて調べてみた その1
【前提条件】
【概要】
今回からラムダのメインとも言えるStreamAPIです。
StreamAPIはリストなどで並行処理を行うためのAPIです。
並行処理を行うためのAPIではありますが、
並行処理ではなくても使用できるものです。
StreamAPIでは並行処理を行うための
ベースとなるStreamインターフェイスが提供されています。
今回は各コレクションからStreamオブジェクトを
作成する方法について調べてみました。
【streamメソッド】
Collection#streamメソッドを使用すると
Streamオブジェクトが生成されます。
final Collection<String> valueList = new ArrayList<>(); final Stream<String> stream = valueList.stream();
Collectionインターフェイスにメソッドが定義されているため、
Collectionインターフェイスを実装していないMapでは
Mapから直接Streamを作成することはできません。
【StreamAPI】
[StreamAPIの使い方]
Streamインターフェイスは要素内のオブジェクトに対する
操作が定義されています。
StreamAPIはStreamインターフェイスが
戻り値のメソッドが多く定義されていて、
メソッドチェインで操作をさせることができます。
valueList.stream().filter(/* 何かしらの処理 */).collect(/* 何かしらの処理 */);
[Streamからの変換]
StreamAPIで要素内のオブジェクトに操作をした後、
リストなどに変換する必要があります。
まずはStreamオブジェクトからListオブジェクトに変換してみます。
final List<String> valueList = new ArrayList<>(); valueList.add("one"); valueList.add("two"); valueList.add("three"); valueList.add("four"); valueList.add("five"); final List<String> collectedList = valueList.stream().collect(Collectors.toList()); collectedList.forEach(System.out::println);
Stream#collectを使うとStreamAPIで操作した結果をリストなどに変換してくれます。
CollectorsクラスにはStreamからListなどに変換するメソッドが定義されています。
サンプルではList⇒Stream⇒Listに変換しているだけなので、
StreamAPIの動きが良くわからないので、
文字列が3文字より多いもののみ抽出してみたいと思います。
valueListの中身は先ほどのサンプルと同じです。
final List<String> filteredList = valueList.stream().filter(v -> v.length() > 3).collect(Collectors.toList()); filteredList.forEach(System.out::println);
実行結果はこうなります。
three four five
Stream自体はListと紐付いているわけではないので、
List⇒Stream⇒Setと言う形に変換することもできます。
final Set<String> filteredSet = valueList.stream().filter(v -> v.length() > 3).collect(Collectors.toSet());
【Collectionインターフェイスを実装していないクラス】
List/Set以外でよく使われるMap、配列は
Streamオブジェクトを直接作成することはできません。
一度、Streamオブジェクトを作成できるクラスに変換する必要があります。
[Map]
MapはSetに変換することでStreamを作成できます。
final Map<String, Integer> valueMap = new LinkedHashMap<>(); valueMap.put("one", 1); valueMap.put("two", 2); valueMap.put("three", 3); valueMap.put("four", 4); valueMap.put("five", 5); final List<String> collectedList = valueMap.keySet().stream().collect(Collectors.toList()); collectedList.forEach(System.out::println);
[Array]
以前のエントリで配列ではforEachするのに
Arrays#asListを使って一度リストに変換すると言うことを書きました。
うらがみさん(@backpaper0)から
「Java 配列はArrays.stream()でStreamに変換してからforEachするという手もありますねー」
と言うコメントをいただきました。
(コメントいただきありがとうございます)
と言うことで早速Array#streamを使ってみます。
final String[] valueArray = { "one", "two", "three", "four", "five" }; Arrays.stream(valueArray).forEach(System.out::println);
Streamオブジェクトに変換して、変換したStreamオブジェクトから
forEachメソッドが使えるようになっています。
出力結果はこうなります。
one two three four five
Streamオブジェクトに変換しているので、filterも使うことができます。
【まとめ】
Streamインターフェイスにはfilter、collectなどのメソッドがあり、
要素内のオブジェクトに対して操作をすることができました。
List、Set、Map、配列からSteramオブジェクトを
生成する方法についてもCollection#strem、Arrays#streamを
使うと言うことがわかりました。
生成の仕方がわかったので
次からStreamAPIの便利な機能を調べていこうと思います。