0. 最初に
開発経験のない新入社員が、Javaを研修で学んだはずなのに見たこともない関数インターフェースに悩まされ、さらには上司の開発陣はもれなくムキムキで泣いているので、自己研鑽と同郷のために記事を投稿する
0.5 APIとは
そもそも、APIは言葉はよく聞きますが、意味をしっかり理解している新人はいますか?私もそこまでしていなかったので、調べました。
「API」とは、「Application Programming Interface」の頭文字です。
アプリケーションをプログラムするうえでのインターフェースと言われれば、多少ピンとくるかもしれませんが、
わかりやすくいうと、ソフトウェアやアプリケーションなどの一部を外部に向けて公開することにより、第三者が開発したソフトウェアと機能を共有できるようにしてくれるもので、外部とのやり取りを行い、よりシステム構築を簡易的に汎用的にしているみたいです。
要するに我々の味方です。
ですから、ここから先に説明するStreamもコードの可読性を上昇させたりと、いいことしかないというわけです
1. Stream API
StreamにはこのようにStreamの取得、中間操作、終端操作にわかれています。
public static void main(String[] args) {
List<String> meList = Arrays.asList("ogi", "suganami", "suzuki", "tomita");
meList.stream() // streamの取得
.filter(i -> i.length() % 2 == 0) // 中間操作
.forEach(i -> System.out.println(i)); // 終端操作
}
今回のサンプルではstream取得後、中間操作として「filter」メソッドを使っています。
名前の通り、コレクションの要素をフィルタリングするものです。
filterメソッドには T -> boolean となるラムダ式を渡してあげます。
今回の場合だと、文字列の長さが偶数の時、TRUEが返ってきます。
終端処理として「forEach」メソッドを使っています。
これはJavaでは確かにforeachないんですが拡張for文と同じ感覚です。
中間要素には様々なメソッドが存在していて、それを有名なものをいくつか紹介してきたいと思います。
2 中間操作のメソッド
以下によく用いられるメソッドを紹介していきます。
filterメソッド
Stream<T> filter(Predicate<? super T> predicate)
先ほどのサンプルで挙げたようにフィルタリングをするための中間操作です。
条件に足してTRUEで帰ってきたものをコレクションします。
public static void main(String[] args) {
List<String> meList = Arrays.asList("ogi", "suganami", "suzuki", "tomita");
meList.stream() // streamの取得
.filter(i -> i.length() % 2 == 0) // 中間操作
.forEach(System.out::println); // 終端操作
}
mapメソッド
<R> Stream<R> map(Function<? super T,? extends R> mapper)
Mapメソッドは引数に書かれた処理のそれぞれの要素に対しての結果を返すメソッドになっています。
public static void main(String[] args) {
List<String> meList = Arrays.asList("ogi", "suganami", "suzuki", "tomita");
meList.stream() // streamの取得
.map(i -> i.length() % 2 == 0) // 中間操作
.forEach(System.out::println); // 終端操作
}
この場合、出力結果は以下のようになります
false
true
true
true
sortedメソッド
sortedメソッドを利用することで、要素をソートできます。引数comparatorを省略した場合、要素は自然順ルールで並び替えされます(文字列であれば辞書順、数値であれば大小での比較)。以下は、引数comparatorで独自の比較ルールを設定した例です。文字列の長さが大きい順に並べ替えます
public static void main(String[] args) {
List<String> meList = Arrays.asList("ogi", "suganami", "suzuki", "tomita");
meList.stream() // streamの取得
.sorted((s1, s2) -> s2.length() - s1.length()) // 中間操作
.forEach(System.out::println); // 終端操作
}
この場合、出力結果は以下のようになります
suganami
suzuki
tomita
ogi
3 終端操作のメソッド
こちらいくつか紹介していきたいと思います。
foreachメソッド
中間操作でコレクションされたストリームの各要素に対してアクションを行います。
public static void main(String[] args) {
List<String> meList = Arrays.asList("ogi", "suganami", "suzuki", "tomita");
meList.stream() // streamの取得
.filter(i -> i.length() % 2 == 0) // 中間操作
.forEach(System.out::println); // 終端操作
}
collectメソッド
collect() は、Stream のデータを変形などの処理を行い、必要なデータ型に変換してくれます。
collectは結構有能(?)みたいで、リスト化やグループ化、文字列連結など、多くの機能をもっています。
今回は文字列サンプルなこともあり、文字列連結を紹介します
public static void main(String[] args) {
List<String> meList = Arrays.asList("ogi", "suganami", "suzuki", "tomita");
meList.stream() // streamの取得
.sorted((s1, s2) -> s2.length() - s1.length()) // 中間操作
.collect(Collectors.joining()); // 終端操作
}
ほかにも条件判定系のanyMatch allMatch noneMatchなどが存在します。
詳しくは公式のリファレンスを
参考文献