博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Java8新特性学习(三)- Stream类
阅读量:2441 次
发布时间:2019-05-10

本文共 6207 字,大约阅读时间需要 20 分钟。

Java8新特性学习(三)- Stream类

背景及介绍

这里提到Java8的Stream类并不像Java以前版本的InputStream和OutputStream,他们是几乎不搭边的两个类。Stream类常跟集合处理一起使用,算是集合的一个增强。Stream类比前面提到的Optional类更加通用,原因在于Stream类提供更丰富的API,满足了程序中通用的集合处理方法,且使用lambda方便,较Java7减少较多的代码。

举例说明

使用Stream和lambda编码,可以提高代码效率,对于过滤取值这种常规操作,相比起java7来实现高效简单。下面举例说明,假设我们有一组求职者的简历集合,我们需要从中过滤具有3年以上工作经验,且有高并发技能的Java开发工程师的求职者,得到他们的手机号,进行面试邀约。

public class Resume {
private String name; private Integer workingAge; private List
skillList; private String job; private String phone; }
//java7        List
phoneList = new ArrayList<>(); for (Resume resume : resumeList) {
if (resume.getWorkingAge() < 3) {
continue; } if (!resume.getSkillList().contains("高并发")) {
continue; } if (!"Java".equals(resume.getJob())) {
continue; } phoneList.add(resume.getPhone()); }
//java8        List
phoneList = resumeList.stream() .filter(resume -> resume.getWorkingAge() >= 3) .filter(resume -> resume.getSkillList().contains("高并发")) .filter(resume -> "Java".equals(resume.getJob())) .map(Resume::getPhone).collect(Collectors.toList());

重要方法介绍

java.util.Collection#stream#parallelStream

集合类对象可以直接通过stream()/paralleStream()方法创建串行流和并行流。如

List
phoneList = resumeList.stream() .map(Resume::getPhone).collect(Collectors.toList());

of\generate

of()用来显式创建串行的Stream对象,有两个重载方法,一个是元素个数不限,另一个只能传一个值。基础数据类型的流,可以扩展使用IntStream、LongStream、DoubleStream.

特别说明:流只能使用一次,不然会抛异常java.lang.IllegalStateException: stream has already been operated upon or closed.

//of()        Stream
integerStream = Stream.of(1,2,3,4,5,6); integerStream.filter(i -> i > 4).forEach(System.out::println);

这里创建的是串行的运行方式,如果想要创建并行的,可以通过Colletion#parallelStream()方法创建。of()方法暂时没有提供这个特性。

generate()方法可以自己生成控制Stream,这个方法适合用来创建常量的Stream或者随机元素的Stream。generate()是无限生成流的,需要配合limit()来使用.下面举例在1000个数字中随机抽取5个幸运中奖号码.

//generate()Stream.generate(() -> new Random().nextInt(1000)).limit(5).forEach(System.out::println);

filter

filter会对Stream中的所有元素进行过滤,会创建一个新的Stream,其元素均符合过滤条件。如文章开头举例的简历过滤:

//java8        List
phoneList = resumeList.stream() .filter(resume -> resume.getWorkingAge() >= 3) .filter(resume -> resume.getSkillList().contains("高并发")) .filter(resume -> "Java".equals(resume.getJob())) .map(Resume::getPhone).collect(Collectors.toList());

map/flatMap

map和flatMap都可以被用在一个Stream对象上,且都能返回Stream.不同之处在于map操作会对每一个输入返回一个结果,然而flatMap操作会返回任意个(0个/1个/多个)值.这取决于在每个方法上的操作。

map操作接受一个Function,会将传入的每个值都调用改Function,然后得到结果后返回。而flatMap操作会对每个参数产生任意数量结果。在Java编程中,返回任意结果可能会在处理时比较麻烦,需要考虑更多的情况,因为返回值可能是一个值,Array或List。我们可以把flatMap操作可以看成是map操作 + flat操作,首先应用Function得到结果,然后将结果flat出来。而map操作相比flatMap操作则可以视为没有最后的flat操作。下面举例:

@Test    public void testFlatMap() {
List
intList1 = new ArrayList<>(); intList1.add(1); intList1.add(2); List
intList2 = new ArrayList<>(); intList1.add(3); intList1.add(4); List
list = Stream.of(intList1, intList2).flatMap(List::stream).collect(Collectors.toList()); System.out.println(list); //[1, 2, 3, 4] }

再举例,现在有几个单词,想过滤单词中不重复的字母。map操作无法得到,而flatMap可以得到。

//map        List
> sMap = Arrays.stream(words).map(word -> word.split("")) .map(Arrays::stream).distinct() .collect(Collectors.toList()); //flatMap List
sFlatMap = Arrays.stream(words).map(word -> word.split("")) .flatMap(Arrays::stream).distinct() .collect(Collectors.toList()); System.out.println(sFlatMap); //[J, A, V, G, O]

Stream map(Function<? super T, ? extends R> mapper);

Stream flatMap(Function<? super T, ? extends Stream<? extends R>> mapper);

collect

collect方法用于将Stream流中的对象转化还原为流的结果。如

List
asList = stringStream.collect(Collectors.toList()); Map
> peopleByCity = personStream.collect(Collectors.groupingBy(Person::getCity)); Map
>> peopleByStateAndCity = personStream.collect(Collectors.groupingBy(Person::getState, Collectors.groupingBy(Person::getCity)));

anyMatch\allMatch

anyMatch:检测是否流中是否有任一元素满足提供Predicate.

allMatch:检测是否流中是否所有元素满足提供Predicate.

boolean anyMatch = Stream.of(1, 2, 3, 4, 5, 6).anyMatch(i -> i > 6);        System.out.println(anyMatch);//false        boolean allMatch = Stream.of(1, 2, 3, 4, 5, 6).allMatch(i -> i < 20);        System.out.println(allMatch);//true

min\max

根据参数Comparator返回流中最大\小的元素,返回类型是Optional。更多Optional信息,请查看

Optional
optionalMin = Stream.of(1, 2, 3, 4, 5, 6).min((a, b) -> a > b ? 1 : -1); System.out.println(optionalMin.orElse(null));//1 Optional
optionalMax = Stream.of(1, 2, 3, 4, 5, 6).max(Integer::compareTo); System.out.println(optionalMax.orElse(null));//6

skip\limit

skip:返回除去前n个元素之外剩余元素组成的流。如果全部被抛弃,则返回一个空流。

limit:返回最大元素个数不超过n的流

Stream.of(1,2,3,4,5,6).skip(20l).forEach(System.out::print);        Stream.of(1,2,3,4,5,6).limit(3l).forEach(System.out::print);

reduce

reduce是关联累积函数对流的元素进行缩减,并返回缩减之后的Optional类型的结果。

reduce()提供了3种方式使用

1、Optional
reduce(BinaryOperator
accumulator);//返回值是Optional2、T reduce(T identity, BinaryOperator
accumulator);//返回值是T,identity一样的类型3、
U reduce(U identity, BiFunction
accumulator, BinaryOperator
combiner); //返回值是U,identity一样的类型,accumulator累加器,combiner:结合器

举例使用

System.out.println(Stream.of(1,2,3,4,5,6).reduce( (a, b) -> a+b).orElse(0));	System.out.println(Stream.of(1,2,3,4,5,6).reduce(0, (a, b) -> a+b));

这里会对Stream中的元素遍历每一个,进行BinaryOperator的apply操作,并最终返回一个类似合并各元素之后的结果。而我们常用的sum,max,min等操作都是一种特殊的reduce操作。可以看IntStream中min()函数的实现:

public final OptionalInt min() {
return reduce(Math::min); }

总结

  • Stream不是一种数据结构
  • Stream并不会自己存储数据,而是利用原数据进行操作
  • Stream只能使用一次,使用多次会抛出异常
  • 具有串行和并行能力,简单高效就能写出高并发代码

转载地址:http://uhnqb.baihongyu.com/

你可能感兴趣的文章
css界面内容可滚动_带有CSS滚动捕捉点的直观滚动界面
查看>>
wordpress插件_更多WordPress插件可成功进行内容营销
查看>>
javafx 菜单组件_基础6:新菜单组件
查看>>
wordpress滑动验证_WordPress图像滑块:滑动还是不滑动?
查看>>
动画的重构和回流的解决_观看:重构慢动画
查看>>
wordpress 数据库_数据库更改以提高WordPress性能
查看>>
那些可以教的人:GuilhermeMüller访谈
查看>>
css中相对长度单位_看看CSS中的长度单位
查看>>
css css2 css3_CSS很好
查看>>
WordPress 4.0的新功能
查看>>
OptionTree-高级选项
查看>>
gulp sass_Sass的简单Gulp'y工作流程
查看>>
萨斯风格的瓷砖
查看>>
sass导入sass_在5分钟内测试Sass功能
查看>>
webrtc_WebRTC的曙光
查看>>
css:背景图片是否滚动_视频:CSS中的可扩展背景
查看>>
vux flexbox使用_3种现代工具如何使用Flexbox网格
查看>>
首先看一下Themosis,一个适用于WordPress开发人员的框架
查看>>
wordpress优化_使用P3优化WordPress性能
查看>>
wordpress图像大小_8个WordPress插件来创建令人敬畏的图像效果
查看>>