资讯专栏INFORMATION COLUMN

Java 8之stream进阶

Jaden / 2491人阅读

摘要:获取每个元素的字符串长度放入新流中,然后转为类型。归约归约就是把整个流归约成一个值的操作,比如求集合中最大的元素所有元素值的和之类的操作。

前言:

上一篇文章 Java 8之stream介绍和使用 中讲解了stream的定义和用法,简单介绍几个最基本最常用的方法,其实stream还有更强大的功能,这篇文章就会给大家介绍stream的进阶用法。

筛选:

在上一篇文章中我们介绍了使用filter方法来筛选元素,filter方法接受一个Predicate类型的参数,我们可以传入一个Lamada表达式或者方法引用,原理在 Java 8之方法引用和Lambda表达式 中已经将结果。我们实际上是传入了一个条件,然后筛选出符合条件的元素,例如下面的这行代码就是筛选出年龄大于20的人。

List list = peoples.stream().filter(person -> person.getAge()>20).collect(toList());

实际上stream还有别的方法可以进行筛选,下面我们来介绍几个常用的。

distinct,这个方法可以帮助我们去重

List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream().filter(i -> i % 2 == 0).distinct().forEach(System.out::println);

limit,这个方法可以让我们只取stream中的前几个,值得注意的是当我们用Set集合来存储元素时,因为Set是无序的,所以每次我们取到的前几个元素也会是无序的。

List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream().limit(3).forEach(System.out::println);

skip,这个方法可以让我们跳过元素,跳过多少个元素由我们指定。

List numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4);
numbers.stream().skip(3).forEach(System.out::println);

映射:

我们经常遇到从对象中抽取自己需要的元素放入一个新的类型的集合中的情况,这就是映射操作,而stream在这方面也提供了非常强大的支持。

map,这个方法接受一个Lambda表达式,它会遍历整个流把这个函数作用到每个元素上,然后把输出的结果放到一个新流中。

// 获取每个元素的name属性放入一个新流中,然后把这个流转为List类型。
List names = peoples.stream().map(Person::getName).collect(toList());
// 获取每个元素的字符串长度放入新流中,然后转为List类型。
List words = Arrays.asList("AA", "B", "CCC", "DDDDDD");
List wordLengths = words.stream().map(String::length).collect(toList());

flatmap,这个方法比较特殊,它的作用是把多个相同类型的流连成一个流,我们看下面的代码,目的是为了把集合中的字符串都拆成单个字符然后放到一个集合,但是如果直接用map方法的话返回的ListString[]类型的,这是因为word.split("")返回的结果就是这个类型的。

List words = Arrays.asList("Hello", "world");
List list = words.stream().map(word -> word.split("")).collect(toList());

在这里要提到Arrays.stream()这个方法,它的作用是接受一个数组,然后把这个数组里的元素转为一个流,所以我们可以尝试使用这个方法来改进下上面的代码。但是我们发现还是有问题,返回集合类型是Stream,因为map(Arrays::stream)把数组里的每个元素都弄成了一个流。

List words = Arrays.asList("Hello", "world");
List> list = words.stream().map(word -> word.split(""))
    .map(Arrays::stream).collect(toList());

现在flatmap的作用就出来了,我们把代码改进下,改成使用flatmap接受Arrays::stream,它的作用正是在上面map(Arrays::stream)的基础上把集合里的流里面的元素合并成一个流,所以返回的List类型就是String类型的。

List words = Arrays.asList("Hello", "world");
List list = words.stream().map(word -> word.split(""))
    .flatmap(Arrays::stream).collect(toList());

匹配:

stream同样也提供了很多方法来检查集合中是否包含了某个指定的值。注意,这些方法都属于 终端操作 ,也就是说调用了这些方法就会关闭流。

allMatch

List numbers = Arrays.asList("Hello", "World");
boolean flag = numbers.stream().allMatch(string -> string.contains("z"));
System.out.println(flag);

anyMatch,这个方法会检查流中是否至少有一个元素匹配给定的值,返回一个boolean值。

List numbers = Arrays.asList("Hello", "World");
boolean flag = numbers.stream().anyMatch(string -> string.contains("z"));
System.out.println(flag);

noneMatch,这个方法则是和allMatch方法做相反的操作。

List numbers = Arrays.asList("Hello", "World");
boolean flag = numbers.stream().noneMatch(string -> string.contains("z"));
System.out.println(flag);

查找:

对于集合的操作最重要的就是从中查找符合条件的数据了,我们来看下面的方法。

findAny,这个方法需要配合filter方法使用,返回把筛选出来的第一个元素。注意,这里返回的是Optional类型的对象,这个对象是Java 8新增的专门为了防止返回数据的时候遇到null的情况,后续再作详细了解,目前只需要知道它有个isPresent方法来判断元素是否为空,get方法用来取值。

List numbers = Arrays.asList("Hello", "World");
Optional optional= numbers.stream().filter(string -> string.contains("l")).findAny();
if(optional.isPresent()){
    System.out.println(optional.get());
}

findFirst,这个方法是用来取流中第一个元素的,目前看来好像没什么用,但是有时候我们可能会对流进行复杂的筛选,再选取筛选后的流中第一个元素。

List numbers = Arrays.asList("Hello", "World");
Optional optional= numbers.stream().findFirst();
System.out.println(optional.toString());

归约:

归约就是把整个流归约成一个值的操作,比如求集合中最大的元素、所有元素值的和之类的操作。

reduce,这个方法就是用来对元素的值进行操作的,我们这里做加法运算。它接受两个参数,第一个是初始值,就是开始计算前就已经有一个数值了。第二个参数是一个Lambda表达式,用来对各个元素做计算。

List list = Arrays.asList(1,2,3,4,5);
int sum = list.stream().reduce(0,(a,b) -> a - b);
System.out.println(sum);

在Java 8中Integer中新增了一个sum方法,它的作用和上面的Lambda表达效果一样,所以我们可以使用这个方法的方法引用来简化代码。

List list = Arrays.asList(1,2,3,4,5);
int sum = list.stream().reduce(0,Integer::sum);
System.out.println(sum);

我们还可以用这个方法来求最大值和最小值,在Integer中还新增了minmax方法,等同于(x, y) -> x < y ? x : y(x, y) -> x > y ? x : y,这样我们就可以求出流中的最大值和最小值了。

Optional min = numbers.stream().reduce(Integer::min);
Optional min = numbers.stream().reduce(Integer::max);

以上就是stream的筛选、查找、匹配和归约操作中比较常用的方法了,下面还会介绍分组、分区等功能。

文章版权归作者所有,未经允许请勿转载,若此文章存在违规行为,您可以联系管理员删除。

转载请注明本文地址:https://www.ucloud.cn/yun/76554.html

相关文章

  • Java 8stream实际应用

    摘要:前言在前面的之介绍和使用和之进阶中讲了的使用方式和一些常用的方法,这篇文章就来演示一下的实际应用。实际应用先创建一个订单类和商品类,每个订单都有年份商品数量和商品对象属性,而商品类里面则包含了名字和价格属性。 前言: 在前面的 Java 8之stream介绍和使用 和 Java 8之stream进阶 中讲了stream的使用方式和一些常用的方法,这篇文章就来演示一下stream的实际应...

    jonh_felix 评论0 收藏0
  • Java8的CompletableFuture进阶

    摘要:方法接收的是的实例,但是它没有返回值方法是函数式接口,无参数,会返回一个结果这两个方法是的升级,表示让任务在指定的线程池中执行,不指定的话,通常任务是在线程池中执行的。该的接口是在线程使用旧的接口,它不允许返回值。 简介 作为Java 8 Concurrency API改进而引入,本文是CompletableFuture类的功能和用例的介绍。同时在Java 9 也有对Completab...

    SunZhaopeng 评论0 收藏0
  • Java核心技术教程整理,长期更新

    以下是Java技术栈微信公众号发布的关于 Java 的技术干货,从以下几个方面汇总。 Java 基础篇 Java 集合篇 Java 多线程篇 Java JVM篇 Java 进阶篇 Java 新特性篇 Java 工具篇 Java 书籍篇 Java基础篇 8张图带你轻松温习 Java 知识 Java父类强制转换子类原则 一张图搞清楚 Java 异常机制 通用唯一标识码UUID的介绍及使用 字符串...

    Anchorer 评论0 收藏0
  • Java 总结

    摘要:中的详解必修个多线程问题总结个多线程问题总结有哪些源代码看了后让你收获很多,代码思维和能力有较大的提升有哪些源代码看了后让你收获很多,代码思维和能力有较大的提升开源的运行原理从虚拟机工作流程看运行原理。 自己实现集合框架 (三): 单链表的实现 自己实现集合框架 (三): 单链表的实现 基于 POI 封装 ExcelUtil 精简的 Excel 导入导出 由于 poi 本身只是针对于 ...

    caspar 评论0 收藏0
  • 你和阿里资深架构师间,差的不仅仅是年龄(进阶必看)

    摘要:导读阅读本文需要有足够的时间,笔者会由浅到深带你一步一步了解一个资深架构师所要掌握的各类知识点,你也可以按照文章中所列的知识体系对比自身,对自己进行查漏补缺,觉得本文对你有帮助的话,可以点赞关注一下。目录一基础篇二进阶篇三高级篇四架构篇五扩 导读:阅读本文需要有足够的时间,笔者会由浅到深带你一步一步了解一个资深架构师所要掌握的各类知识点,你也可以按照文章中所列的知识体系对比自身,对自己...

    huaixiaoz 评论0 收藏0

发表评论

0条评论

Jaden

|高级讲师

TA的文章

阅读更多
最新活动
阅读需要支付1元查看
<