Java Lamda Stream API

举报
Jet Ding 发表于 2020/09/29 10:52:11 2020/09/29
【摘要】 现在我们通过本文学习一下Java 8 Streams从创建到并行执行的实际用法。

现在我们通过本文学习一下Java 8 Streams从创建到并行执行的实际用法。

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

核心API类是Stream<T>

1    Stream创建

stream()of()方法的帮助下,可以从不同的元素源(如集合或数组)创建Stream

String[] arr = new String[]{"a""b""c"};

Stream<Stringstream = Arrays.stream(arr);

stream = Stream.of("a""b""c");

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

Stream<Stringstream = list.stream();

 

2      多线程与Stream

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

下面的代码允许对流的每个元素并行运行doWork()方法。

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

 

 

3      Stream 操作

有许多有用的操作可以在流上执行,它们分为中间操作(返回Stream<T>)和终端操作(返回确定类型的结果)。

中间操作允许链式操作。

另外值得注意的是,对Stream的操作不会改变源数据。

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

 

所以,distinct()方法代表的是一个中间操作,它由前一个流的唯一元素创建一个新的流。而count()方法是一个终端操作,它返回流的元素个数。

4      迭代

API有助于替代for-eachwhile循环。它允许专注于操作的逻辑,而不是元素序列的迭代。例如:

for (String string : list) {

    if (string.contains("a")) {

        return true;

    }

}

 

这段代码只要用一行Java 8代码就可以:

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

 

5      筛选

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

例如,如以下列表:

ArrayList<Stringlist = 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("");

 

下面的代码创建了一个List<String>Stream<String>,找到这个流中所有包含char "d "的元素,并创建一个只包含过滤元素的新流。

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

 

6      映射

要通过对Stream的元素应用一个特殊的函数进行转换,并将这些新的元素收集到一个Stream中,我们可以使用map()方法。

List<Stringuris = new ArrayList<>();

uris.add("C:\\My.txt");

Stream<Pathstream = uris.stream().map(uri -> Paths.get(uri));

 

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

如果你有一个流,在这个流中,每个元素都包含自己的元素序列,你想创建这些内部元素的流,你应该使用flatMap()方法。

List<Detaildetails = new ArrayList<>();

details.add(new Detail());

Stream<String> stream

  = details.stream().flatMap(detail -> detail.getParts().stream());

 

 

在这个例子中,我们有一个类型为Detail的元素列表。Detail类包含一个字段PARTS,它是一个List<String>。在flatMap()方法的帮助下,字段PARTS中的每一个元素都将被提取并添加到新产生的流中。之后,初始的Stream<Detail>将丢失。

7      匹配

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

 

8      缩减

Stream API允许在Stream类型的reduce()方法的帮助下,根据指定的函数将一个元素序列还原成某个值。这个方法需要两个参数:第一个--起始值,第二个--累加器函数。

想象一下,你有一个List<Integer>,你想得到所有这些元素和一些初始Integer(在这个例子中为23)的总和。所以,你可以运行下面的代码,结果将是2623+1+1+1)。

List<Integerintegers = Arrays.asList(111);

Integer reduced = integers.stream().reduce(23, (a, b) -> a + b);

 

9      收集

缩减也可以由Stream类型的collect()方法提供。这个操作在将一个流转换为一个CollectionMap,并以单个字符串的形式表示一个流的情况下非常方便。有一个实用类Collectors,它为几乎所有典型的收集操作提供了一个解决方案。对于一些非琐碎的任务,可以创建一个自定义的Collector

 

List<String> resultList 

  = list.stream().map(element -> element.toUpperCase()).collect(Collectors.toList());

 

这段代码使用终端的collect()操作将一个Stream<String>还原成List<String>

10 参考

https://stackify.com/streams-guide-java-8/

https://www.baeldung.com/java-8-streams-introduction

https://www.baeldung.com/java-8-streams


【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。