Java8 Stream:实例详细介绍遍历、筛选、归约、分组、聚合操作

一、什么是Stream

Stream是java8新增的类,同时也是新加的一个特性。它的作用是将数据以流的形式处理,该类提供了流操作的方法,数据从源流入,中间可以经过这些操作对数据流做出处理,最后流出,Stream就像一个管道一样,数据是流经管道中的水。流经Stream的这些数据来源可以是数组,集合,甚至是一个对象。
在Stream里面,数据经过的操作分为两种:

  1. 中间操作:对数据流做一些处理,之后以流的形式流出,中间操作后面还可以有其他操作,中间操作又可以细分为无状态(Stateless)和有状态的(Stateful),无状态表示元素的处理不受之前元素的影响;有状态表示该操作只有拿到所有元素之后才能继续下去;
  2. 终端操作:是本次流处理的最后一个操作,每个流只能进行一次终端操作,终端操作又可以细分为短路操作和非短路操作,短路操作是指遇到符合条件的元素就可以终止处理返回最终结果,非短路操作是指必须处理所有元素才能得到最终结果。

下图罗列了Stream的常用操作:
在这里插入图片描述

Stream还有以下特性:

  1. Stream在执行上图这些操作的时候,不会修改数据源的数据,如果数据源是一个数组,执行一系列操作后,数组中的数据保持原样不变;
  2. 如果Stream操作中没有终端操作,那么不会触发中间操作对数据处理;
  3. Stream对象一旦执行过终端操作,就不能再次使用,只能新建流;
  4. 流可以单线程或者多线程处理数据,分别称为顺序流和并行流。

二、创建Stream

1、Stream静态方法创建

Stream提供了generate(),concat(),empty(),iterate(),of()方法创建Stream对象。

  //generate() 要求入参是Supplier接口实现类,这里使用了方法引用,limit方法表示只取前五个数字
  Stream s1=Stream.generate(Math::random).limit(5);
  s1.forEach(x-> {
   
   
      System.out.print(x+",");
      return;
  });

  System.out.println('\n');
  //of的入参要求是一个数组
  Stream s2=Stream.of(1,2,3,4,5);
  s2.forEach(x-> {
   
   
      System.out.print(x+",");
      return;
  });

  System.out.println('\n');
  //iterate方法的第一个入参是种子,第二个入参表示从种子产生后续元素的规则
  Stream s3=Stream.iterate(1,i->(i+1)).limit(5);
  s3.forEach(x-> {
   
   
      System.out.print(x+",");
      return;
  });

执行结果为:

0.41496598483096414,0.0688991791546536,0.22740053512262426,0.003628221833255507,0.8909583300521023,

1,2,3,4,5,

1,2,3,4,5,

concat()方法用于将两个Stream对象结合起来形成一个流对象。
empty()方法用于产生一个空流,该流里面没有任何元素。

2、Arrays.stream()创建流

Integer[] a=new Integer[5];
a[0]=1;a[1]=2;a[2]=3;a[3]=4;a[4]=5;
Stream s2=Arrays.stream(a);
s2.forEach(x-> {
   
   
    System.out.print(x+",");
    return;
});

运行结果:

1,2,3,4,5,

Arrays.stream()也可以创建IntStream、LongStream等流对象,这些流对象是java提供的专门处理int、long等类型的,它们对int、long等类型做了针对性的优化处理。注意IntStream、LongStream与Stream没有继承关系。

3、Collection.stream()创建流

Collection.stream()用于创建顺序流,Collection还提供了parallelStream()可以创建并行流。

List list=new ArrayList<>();
list.add(1);list.add(2);list.add(3);list.add(4);list.add(5);

Stream s2=list.stream();
s2.forEach(x-> {
   
   
    System.out.print(x+",");
    return;
});

运行结果:

1,2,3,4,5,

三、Stream操作

下面先介绍终端操作,之后介绍中间操作。

1、foreach()遍历

foreach()上面已经展示过了,它遍历流中的每个元素,对每个元素使用入参对象处理。

2、find()查找/match()匹配

List<Integer> list=new ArrayList<>();
list.add(5);list.add(4);list.add(1);list.add(3);list.add(2);

Optional o1=list.stream().filter(x->(x<=3)).findAny();//返回流中任意一个元素
System.out.println(o1.get());
Optional o2=list.stream().filter(x->(x<=3)).findFirst();//返回流中第一个元素
System.out.println(o2.get());

System.out.println(list.stream().allMatch(x->(x<=3)));//检查流中所有的元素是否都符合条件要求
System.out.println(list.stream().anyMatch(x->(x<=3)));//检查流中是否有符合条件要求的元素
System.out.println(list.stream().noneMatch(x->(x<=3)));//检查流中所有的元素是否都不符合条件要求

运行结果:

1
1
false
true
false

3、reduce()规约

规约相当于缩减,将流中的多个元素通过某种操作缩减为一个元素。
Stream提供了入参三个重载方法:

Optional<T> reduce(BinaryOperator<T> accumulator);
T reduce(T identity, BinaryOperator<T> accumulator);
<U> U reduce(U identity,BiFunction<U, ? super T, U> accumulator,BinaryOperator<U> combiner);

先演示一下如何使用这些方法。

List<Integer> list=new ArrayList<>();
list.add(5);list.add(4);list.add(1);list.add(3);list.add(2);

//元素求和
Optional<Integer> o1=list.stream().reduce(Integer::sum);
System.out.println(o1.get());
//元素求最大值
Optional<Integer> o2=list.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值