注目記事

【Javaコード入門】Stream API_③Streamによる中間処理

Streamの中を流れる値(個々の要素)を加工/フィルターするプロセスが、中間処理です。ひとつのStream処理につき、中間処理は0個以上複数持つことが可能です。

値を加工する – mapメソッド

public <R> Stream<R> map​(Function<? super T,​? extends R> mapper)
 T:元の要素の型
 R:加工後の要素の型
 mapper:要素を加工するためのラムダ式

mapメソッドを利用することで、Stream内を流れる値を加工できます。加工前後のデータ型は変化しても構いません。

たとえば以下は、与えられた文字列リストから先頭文字のコードポイント値を求める例です。

StreamMap.java

package com.example.mynavi.streamapi;
 
import java.util.stream.Stream;
 
public class StreamMap {
  public static void main(String[] args) {
    Stream.of("あいうえお", "かきくけこ", "さしすせそ")
      .map(s -> s.codePointAt(0))
      .forEach(System.out::println);
  }
}

  1. 12354
  2. 12363
  3. 12373

mapメソッドによる加工前後のデータ型は変化しても構いません。この例であれば、加工前はStream<String>ですが、加工後はStream<Integer>です。

ちなみに、加工後に基本型Streamを生成したいならば、mapメソッドの代わりにmapToInt/mapToLong/mapToDoubleメソッドがあります(この例であればmapToIntメソッドを利用することでIntStreamを生成できます)。基本型Streamを利用することで、ボクシングのオーバーヘッドを軽減できます。

条件で値を絞り込む – filterメソッド

public Stream<T> filter(Predicate<? super T> predicate)
 T:要素の型
 predicate:要素を判定するラムダ式

filterメソッドは、与えられたラムダ式(predicate)がtrueを返した要素だけを残します。たとえば以下は、「あ」で始まる要素だけを残す例です。

StreamFilter.java

package com.example.mynavi.streamapi;
 
import java.util.stream.Stream;
 
public class StreamFilter {
  public static void main(String[] args) {
    Stream.of("あかさか", "さくらぎちょう", "あおもり")
     .filter(s -> s.startsWith("あ"))
     .forEach(System.out::println);
  }
}

  1. あかさか
  2. あおもり

特定範囲の要素だけを取得する – skip/limitメソッド

public Stream<T> skip(long n)
public Stream<T> limit(long max)
 T:要素の型
 n:スキップする要素数
 max:取得する要素数

skip/limitメソッドを利用することで、Streamからn+1~n+max番目の要素を取り出せます。

StreamSkip.java

package com.example.mynavi.streamapi;
 
import java.util.stream.IntStream;
 
public class StreamSkip {
  public static void main(String[] args) {
    IntStream.range(1, 10)
      .skip(5)
      .limit(3)
      .forEach(System.out::println);
  }
}

  1. 6
  2. 7
  3. 8

この例であれば、先頭5番目の要素をスキップして6番目の要素から3個の要素を取得する、という意味になります。

値を並べ替える – sortedメソッド

public Stream<T> sorted(Comparator<? super T> comparator)
 T:要素の型
 comparator:比較ルール

sortedメソッドを利用することで、要素をソートできます。引数comparatorを省略した場合、要素は自然順ルールで並び替えされます(文字列であれば辞書順、数値であれば大小での比較)。以下は、引数comparatorで独自の比較ルールを設定した例です。文字列長が長い順に並べ替えます。

StreamSorted.java

package com.example.mynavi.streamapi;
 
import java.util.stream.Stream;
 
public class StreamSorted {
 
  public static void main(String[] args) {
    Stream.of("あかさか", "さくらぎちょう", "よよぎ")
     .sorted((s1, s2) -> s2.length() - s1.length())
     .forEach(System.out::println);
  }
}

  1. さくらぎちょう
  2. あかさか
  3. よよぎ

引数comparatorでは、引数(s1、s2)として渡された要素を比較して、

  • s1 < s2であれば負数
  • s1 = s2であれば0
  • s1 > s2であれば正数

を返します。この例であれば、s1、s2の文字列長の差を求めることで、文字列長の大小を表しています。

Stream API_目次
Stream APIの基本
Streamの生成
Streamによる中間処理
Streamの終端処理

監修

山田祥寛(有限会社 WINGSプロジェクト)
静岡県榛原町生まれ。一橋大学経済学部卒業後、NEC にてシステム企画業務に携わるが、2003年 4 月に念願かなってフリーライターに転身。Microsoft MVP for Visual Studio and Development Technologies。執筆コミュニティ「WINGSプロジェクト(https://wings.msn.to/)」の代表でもある。主な著書に『改訂 3 版JavaScript 本格入門』(技術評論社)、「独習シリーズ(C#・Python・PHP・Ruby・JSP&サーブレットなど)」(翔泳社)、「速習シリーズ(ASP.NET Core・Vue.js・React・TypeScript・ECMAScript、Laravel など)」(Amazon Kindle)など。売り上げの累計は100万部を超える。