1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

JavaのStreamAPIについて

Posted at

はじめに

StreamAPIの入門者向け記事です。
StreamAPIで使われるラムダ式については解説していません。(この記事を参考にしてください)

StreamAPIとは

StreamAPIはJava SE8から追加されたコレクションの取り扱いをいい感じにできる機能です。
基本的には以下の流れで処理をします。

  1. Streamを取得
  2. 中間操作を実行してStreamの要素に対して操作を加える
  3. 終端操作を実行して結果を取得

java.util.streamパッケージに関連するクラスがまとめられています。

使い方

Streamの種類

主にStreamオブジェクトは以下のものがあります。
通常のStreamは参照型の値しか扱うことができないので、プリミティブ型を扱うStreamが別に用意されています。

Stream 扱う型
Stream 参照型
IntStream int型
LongStream long型
DoubleStream double型

Streamの取得方法

以下のようなパターンでStreamが取得できます。

// ListからStreamを取得
List<String> list = List.of("twitter", "instagram", "facebook");
Stream<String> stream = list.stream();

// 配列からStreamを取得
String[] strArraly = {"twitter", "instagram", "facebook"};
Stream<String> stream = Stream.of(strArraly);

// プリミティブ型を扱うStreamを取得
IntStream stream = IntStream.of({1, 2, 3, 4, 5});

// Stream.of()だとInteger型を扱うStreamが取得される
Stream<Integer> stream = Stream.of({1, 2, 3, 4, 5});

// 要素数が無限
Stream<Integer> stream = Stream.generate(() -> new Random().nextInt());

中間操作

Stream内の要素を操作し、新しいStreamを返す操作です。
新しいStreamを返すことからメソッドチェーンでつないで記述することができます。

中間操作一覧(一部)
メソッド 内容 引数
filter 条件に一致する要素のみのStreamを返す Predicate
map 別の型を扱うStreamを返す Function
mapToInt intStreamを返す Function
distinct 要素の重複を排除したStreamを返す
※equalsメソッドでtrueを返すもの
なし
limit 指定された要素数のStreamを返す int
skip 指定された数分の要素を飛ばしたStreamを返す int
sorted 引数で指定した順序に従ってソートされたStreamを返す
※引数なしの場合は自然順序に従う
Comparator
peek 現在の要素に対して関数を適用し、Streamを返す Consumer

使用例

// tを含む要素のみを扱うStreamに変換
Stream<String> stream = List.of("twitter", "instagram", "facebook").stream().filter(str -> str.contains("t")); 
// "twitter", "instagram" を扱うStream<String>を返す

// 文字列の文字数を扱うStreamに変換
Stream<Integer> stream = List.of("twitter", "instagram", "facebook").stream().map(str -> str.length());
// 7, 9, 8を扱うStream<Integer>を返す

// IntStream型のStreamに変換
IntStream stream = List.of("twitter", "instagram", "facebook").stream().mapToInt(str -> str.length());
// 7, 9, 8を扱うIntStreamを返す

// 重複を排除
Stream<String> stream = List.of("twitter", "instagram", "facebook", "twitter").stream().distinct();
// "twitter", "instagram", "facebook"を扱うStream<String>を返す

// 要素数を限定する
Stream<String> stream = Stream.generate(() -> new Random().nextInt()).limit(5);
// 5つの乱数を扱うStream<Integer>を返す

// 最初の要素を指定分スキップする
Stream<String> stream = List.of("twitter", "instagram", "facebook").stream().skip(1);
// "instagram", "facebook"を扱うStream<String>を返す

// 要素の順番を並び替える
Stream<String> stream = List.of("twitter", "instagram", "facebook").stream().sorted();
// "facebook", "instagram", "twitter"を扱うStream<String>を返す

// 要素の状態を表示する
Stream<String> stream = List.of("twitter", "instagram", "facebook").stream().peek(str -> System.out.print(str + " "));
// コンソールに twitter instagram facebookと表示し、"twitter", "instagram", "facebook"を扱うStream<String>を返す

// メソッドチェーン
List.of("twitter", "instagram", "facebook").stream().map(str -> str.length()).filter(len -> len > 7);
// 7, 9, 8を扱うStream<Integer>に変換し、9, 8を扱うStream<Integer>を返す

終端操作

Streamオブジェクトを最終的に処理する操作です。
一つのStreamオブジェクトに対して1回しか呼び出せません。

以下の例は実行時に例外が発生します。

Stream<String> stream = List.of("twitter", "instagram", "facebook").stream();
stream.forEach(str -> System.out.println(str));
stream.forEach(str -> System.out.println(str)); // IllegalStateExceptionがスローされる
終端操作一覧
メソッド 内容 引数 戻り値
forEach Streamの要素一つ一つに処理を行う Consumer void
count Streamの要素数を返す なし int
collect Streamの要素を持つコレクションを返す Collector
Supplier, BiConsumer, BiConsumer
Collectorで指定した型
reduce Streamの要素を結合して返す BinaryOparator
T(初期値), BinaryOperator
Optional<T>
T

collectメソッドの引数、Collectorは奥が深いので[Java]StreamのCollectorsのメモを参照してください。

// stream要素
Stream<String> stream = List.of("twitter", "instagram", "facebook", "twitter").stream();

// 要素を1つずつコンソールに出力
stream.forEach(str -> System.out.println(str));

// 要素の個数を取得
long count = stream.count();

// 要素をリストにして取得(Collectorsを使用する)
List<String> list  = stream.map(str -> str.toUpperCase()).collect(Collectors.toList());

// 要素をリストにして取得(関数型インタフェースを使用する。↑と同じ)
List<String> list = stream.collect(() -> new ArrayList<>(), 
    (List<String> list, String str) -> list.add(str),
    (List<String> left, List<String> right) -> left.addAll(right)
);

// 要素の文字数を合計して取得
Integer length = stream.map(str -> str.length()).reduce(0, (a, b) -> a + b);

// 初期値を指定しなかった場合はOptionalが返される
Optional<Integer> length = stream.map(str -> str.length()).reduce((a, b) -> a + b);
1
0
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
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?