Stream API の filter
、peek
、collect
をメソッド化または引数にする方法
Stream API の filter
、peek
、collect(Collectors.toList())
を利用した処理は、メソッド化や関数型インターフェースを用いたパラメータ化が可能です。
仕事で困っていたのでChatGPTの答えを貼り付け。
以下に、いくつかの方法を紹介します。
1. ストリーム処理をメソッド化する
(1) Stream を引数にして処理を適用
Stream の処理を メソッドとして切り出す 方法です。
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamExample {
// ストリーム処理をメソッド化
public static List<String> processStream(Stream<String> stream) {
return stream
.filter(s -> s.startsWith("A")) // "A" で始まるものをフィルタ
.peek(s -> System.out.println("Filtered: " + s)) // ログ出力
.collect(Collectors.toList()); // リスト化
}
public static void main(String[] args) {
List<String> data = List.of("Apple", "Banana", "Avocado", "Orange");
// メソッドを使う
List<String> result = processStream(data.stream());
System.out.println(result); // [Apple, Avocado]
}
}
ポイント
-
Stream<String>
を受け取るメソッドを定義し、filter
・peek
・collect
を適用。 - 任意の
Stream
に適用できる汎用的なメソッドとして利用可能。
2. 関数型インターフェース (Function
) を使ってメソッドの引数に渡す
ストリーム処理を Function<Stream<T>, List<T>>
にまとめ、メソッドの引数として渡す 方法です。
import java.util.List;
import java.util.function.Function;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamExample {
// 汎用的なストリーム処理
public static <T> List<T> applyStreamFunction(Stream<T> stream, Function<Stream<T>, List<T>> function) {
return function.apply(stream);
}
public static void main(String[] args) {
List<String> data = List.of("Apple", "Banana", "Avocado", "Orange");
// 処理を Function として定義
Function<Stream<String>, List<String>> processStream = s -> s
.filter(str -> str.startsWith("A"))
.peek(str -> System.out.println("Filtered: " + str))
.collect(Collectors.toList());
// メソッドに関数を渡して適用
List<String> result = applyStreamFunction(data.stream(), processStream);
System.out.println(result); // [Apple, Avocado]
}
}
ポイント
-
Function<Stream<T>, List<T>>
を使い、ストリーム処理の適用方法を柔軟に変更できる。 - どのような
Stream<T>
にも適用できる汎用メソッド。
3. UnaryOperator<Stream<T>>
を使う
UnaryOperator<Stream<T>>
を使って、ストリーム自体を操作する方法です。
import java.util.List;
import java.util.function.UnaryOperator;
import java.util.stream.Collectors;
import java.util.stream.Stream;
public class StreamExample {
// UnaryOperator を使ってストリーム処理を抽象化
public static <T> List<T> processWithOperator(List<T> data, UnaryOperator<Stream<T>> operator) {
return operator.apply(data.stream()).collect(Collectors.toList());
}
public static void main(String[] args) {
List<String> data = List.of("Apple", "Banana", "Avocado", "Orange");
// ストリーム処理を UnaryOperator として定義
UnaryOperator<Stream<String>> streamOperator = s -> s
.filter(str -> str.startsWith("A"))
.peek(str -> System.out.println("Filtered: " + str));
// メソッドに処理を渡して適用
List<String> result = processWithOperator(data, streamOperator);
System.out.println(result); // [Apple, Avocado]
}
}
ポイント
-
UnaryOperator<Stream<T>>
はStream<T>
を受け取り、処理を適用したStream<T>
を返す。 -
collect(Collectors.toList())
はメソッド内で適用することで、ストリーム操作を統一できる。
まとめ
方法 | メリット | デメリット |
---|---|---|
1. メソッド化 (Stream を引数にする) |
簡潔で分かりやすい |
Stream<T> を都度渡す必要がある |
2. Function<Stream<T>, List<T>> を使う |
汎用的に使いやすい |
Function の記述がやや複雑 |
3. UnaryOperator<Stream<T>> を使う |
ストリーム処理を簡潔にカプセル化 |
collect(Collectors.toList()) を適用する箇所に注意 |
おすすめ
- 一番シンプルなのは ① のメソッド化
- 柔軟性を求めるなら ② の
Function
を引数にする方法 - ストリーム自体の操作に重点を置くなら ③ の
UnaryOperator
どれを選ぶかは、「どの程度の汎用性を求めるか」 によります。
シンプルなケースではメソッド化、より柔軟にするなら Function
や UnaryOperator
を使うのが良いでしょう。