跳至主要內容

01. Stream流

LiuSongLing大约 4 分钟javajavaStream

本文快速浏览 java 8 添加的主要新功能之一 - Streams。

1.Stream API

Java 8 中的主要新特性之一是引入了流功能 java.util.stream ,它包含用于处理元素序列的类。

中心 API 类是 Stream<T>

2.创建Stream

借助 stream() 和 of() 方法,可以从不同的元素源(例如集合或数组)创建流:

String[] arr = new String[]{"a", "b", "c"};
Stream<String> stream = Arrays.stream(arr);
stream = Stream.of("a", "b", "c");

在 Collection 接口中添加了一个 stream() 默认方法,并允许使用任何集合作为元素源来创建 Stream<T>:

Stream<String> stream = list.stream();

3.Stream中的多线程

Stream API 还通过提供 parallelStream() 方法简化了多线程处理,该方法以并行模式对流的元素运行作。

list.parallelStream().forEach(element -> doWork(element));

4.Stream动作

可以对流执行许多有用的动作。

它们分为中间动作 (return Stream<T>) 和终端动作 (返回确定类型的结果)。

中间动作允许串联,而且对 streams 的动作不会更改源。

long count = list.stream().distinct().count();

distinct() 方法表示一个中间动作,它创建一个包含前一个流的唯一元素的新流。count() 方法是一个终端动作,它返回 stream 的大小。

5,迭代

Stream API 有助于 substitute for、for-each 和 while 循环。

for (String string : list) {
    if (string.contains("a")) {
        return true;
    }
}

使用 Stream 后:

boolean isExist = list.stream().anyMatch(element -> element.contains("a"));

6.过滤

filter() 方法允许我们选择满足谓词的元素流。

以下代码创建 List<String>Stream<String>,查找此流中包含字符 “d” 的所有元素,并创建一个仅包含筛选元素的新流:

ArrayList<String> list = new ArrayList<>();
list.add("One");
list.add("OneAndOnly");
list.add("Derek");
list.add("Change");
list.add("factory");
list.add("justBefore");
list.add("Italy");
list.add("Italy");
list.add("Thursday");
list.add("");
list.add("");

Stream<String> stream = list.stream().filter(element -> element.contains("d"));

7.映射

通过对 Stream 的元素应用特殊函数来转换它们并将这些新元素收集到 Stream 中,我们可以使用 map() 方法:

List<String> uris = new ArrayList<>();
uris.add("C:\\My.txt");
Stream<Path> stream = uris.stream().map(uri -> Paths.get(uri));

上面的代码通过将特定的 lambda 表达式应用于初始 Stream 的每个元素,将 Stream<String> 转换为 Stream<Path>

如果你有一个流,其中每个元素都包含它嵌套元素,并且你想创建一个所有内部元素的扁平流,你应该使用 flatMap() 方法:

List<Detail> details = new ArrayList<>();
details.add(new Detail());
Stream<String> stream
  = details.stream().flatMap(detail -> detail.getParts().stream());

在此示例中,我们有一个 Detail 类型的元素列表。Detail 类包含一个字段 PARTS,该字段是 List<String>

在 flatMap() 方法的帮助下,字段 PARTS 中的每个元素都将被提取并添加到新的结果流中。

8.匹配

Stream API 提供了一组方便的工具,用于根据某些谓词验证序列的元素。为此,可以使用以下方法之一:

anyMatch()、allMatch()、noneMatch()。

boolean isValid = list.stream().anyMatch(element -> element.contains("h")); // true
boolean isValidOne = list.stream().allMatch(element -> element.contains("h")); // false
boolean isValidTwo = list.stream().noneMatch(element -> element.contains("h")); // false

对于空流,具有任何给定谓词的 allMatch() 方法都将返回 true:

Stream.empty().allMatch(Objects::nonNull); // true

同样,anyMatch() 方法总是为空流返回 false:

Stream.empty().anyMatch(Objects::nonNull); // false

9.减少

Stream API 允许借助 Stream 类型的 reduce() 方法,根据指定的函数将元素序列减少到某个值。此方法采用两个参数:first – 起始值,second – 累加器函数。

假设有一个 List<Integer>,并且您希望获得所有这些元素和一些初始 Integer 的总和(在本例中为 23)。

您可以运行以下代码,结果将为 26 (23 + 1 + 1 + 1)。

List<Integer> integers = Arrays.asList(1, 1, 1);
Integer reduced = integers.stream().reduce(23, (a, b) -> a + b);

10.收集

reduce 也可以由 Stream 类型的 collect() 方法提供。在将流转换为 Collection 或 Map 并以单个字符串的形式表示流的情况下,此作非常方便。

有一个实用程序类 Collectors,它为几乎所有典型的收集作提供了解决方案。对于某些重要的任务,可以创建自定义 Collector。

List<String> resultList 
  = list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());