关于Java的Stream API
首先
这是一篇面向StreamAPI初学者的文章。
该文章不涉及StreamAPI中使用的Lambda表达式。(请参考这篇文章)
StreamAPI是什麼
StreamAPI是从Java SE8开始添加的一种功能,可以很好地处理集合的操作。基本上,它遵循以下步骤进行处理。
-
- 获取Stream
-
- 执行中间操作对Stream的元素进行操作
- 执行终端操作获取结果
相关的类被整理在java.util.stream包中。
使用方法
流媒体的类别
主要的Stream对象包括以下内容。
通常的Stream只能处理引用类型的值,因此还专门提供了处理原始类型的Stream。
Stream扱う型Stream参照型IntStreamint型LongStreamlong型DoubleStreamdouble型
获取流的方法
可以通过以下模式获得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を返すPredicatemap別の型を扱うStreamを返すFunctionmapToIntintStreamを返すFunctiondistinct要素の重複を排除したStreamを返す
※equalsメソッドでtrueを返すものなしlimit指定された要素数のStreamを返すintskip指定された数分の要素を飛ばしたStreamを返すintsorted引数で指定した順序に従ってソートされたStreamを返す
※引数なしの場合は自然順序に従うComparatorpeek現在の要素に対して関数を適用し、Streamを返すConsumer
※equalsメソッドでtrueを返すものなしlimit指定された要素数のStreamを返すintskip指定された数分の要素を飛ばしたStreamを返すintsorted引数で指定した順序に従ってソートされたStreamを返す
※引数なしの場合は自然順序に従うComparatorpeek現在の要素に対して関数を適用し、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对象只能调用一次。
以下的示例将在运行时引发异常。
Stream<String> stream = List.of("twitter", "instagram", "facebook").stream();
stream.forEach(str -> System.out.println(str));
stream.forEach(str -> System.out.println(str)); // IllegalStateExceptionがスローされる
终端操作概览
メソッド内容引数戻り値forEachStreamの要素一つ一つに処理を行うConsumervoidcountStreamの要素数を返すなしintcollectStreamの要素を持つコレクションを返すCollector
Supplier, BiConsumer, BiConsumerCollectorで指定した型reduceStreamの要素を結合して返すBinaryOparator
T(初期値), BinaryOperatorOptional<T>
T
Supplier, BiConsumer, BiConsumerCollectorで指定した型reduceStreamの要素を結合して返すBinaryOparator
T(初期値), BinaryOperatorOptional<T>
T
请参考Java Stream中的Collectors的注释,因为collect方法的参数Collector很深奥。
// 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);