Java8——Stream流详解

Stream

Stream是Java8的一个新特性,隶属于java.util包下,它是一个接口类型,里面定义了各种方法方便用于对各类集合进行操作,极大的简化了开发效率。

是什么?

Stream 就类似于一个高级的迭代器,但只能遍历一次,在这过程中也可以对流中的元素执行一些操作,使用forEach方法对集合进行快速的遍历,过滤掉任意长度的字符串、获取每个字符串的首字母,转换数据类型等。

Stream流式思想

Stream流式思想类似于工厂车间的 “生产流水线”,Stream流不是一种数据结构,它不用于保存数据,而是对数据进行加工处理,可以看作为流水线上的一道工序,通过多道工序让一个数据原材料加工成一个商品再对外开放。

获取流的三种方式

第一种是通过Collection接口的stream方法获取

//创建一个List集合对象
List<String> list = new ArrayList<>();
Stream<String> stream = list.stream();

第二种是通过Collection接口的parallelStream方法获取一个并发流

//创建一个list集合
List<String> list = new ArrayList<>();
Stream<String> parallelStream = list.parallelStream();

第三种是通过Stream接口里的of方法获取数组对应的流

 Stream<Object> of = Stream.of(); //直接用Stream接口调用自身的of方法

of方法有两个参数,一个是根据泛型传参,一个是可变长参数类型

List<String> list = new ArrayList<>();
Stream<Object> of1 = Stream.of(list); //传入一个list集合,也可以是其它类型

Stream<Integer> of2 = Stream.of(1, 2, 3); //根据可变参数传值,可以是任意长度

Stream工作流程

Stream流的操作流程是先将集合转为流,然后经过各种循环遍历和筛选的操作,比如过滤、筛选、分组、计算。和最后的计数操作,然后转化成想要的数据,这个数据的形式还是集合本身,也可以按照需求利用count求总数

原始集合 ===> Stream流  ===>筛选操作(遍历、过滤、分组、统计) —> 最终结果

为什么用Stream流

使用某一种技术本质上还是为了提高开发效率,减少代码的冗余,Stream流可以帮助我们高效的去操作集合,通过生产流水线的方式对集合进行删除合并排序修改,并最终返回想要的元素数据或统计数据。这里流水线的意思是说,一批数据元素不需要等待全部元素都完成某些操作才进行下步流程操作,而是可以尽可能的进行下步操作,就好像流水线工厂一样,这为Stream流高效运作提供了基础。Stream流还有一个内部迭代的概念,就是把for循环显示迭代封装了起来,这样可以更方便的并行开发

常用方法概述

方法名方法作用返回值类型方法种类
forEach逐个遍历元素void结尾
filter过滤流元素Stream方法拼接
map映射流Stream方法拼接
skip跳过前几个元素Stream方法拼接
distinct去除重复的元素Stream方法拼接
limit取前几个元素值Stream方法拼接
count统计总数long结尾
concat组合Stream方法拼接

forEach

forEach参数是名为Consumer的接口(Java8的一个函数式接口,这个参数没有返回值,后面也不能再接其它的流方法,其参数语法为 类名 :: 方法名,一般用System类调用print或println方法

示例:

Stream<String> stream = Stream.of("Im","a","stream");
stream.forEach(System.out::print); //print不会换行
stream.forEach(System.out::println); //print不会换行

filter

filter是过滤器的意思,顾名思义就是用来过滤集合元素然后再将其结果打印输出

例如过滤筛选出流中等于10的元素

Stream<Integer> stream = Stream.of(10,20,30);
//使用lambda表达式筛选出等于10的值,然后再调用forEach遍历输出
stream.filter(F -> F == 10).forEach(System.out :: print);

调用String类的方法对字符串进行筛选过滤

Stream<String> stream = Stream.of("I'm","a","stream");
//String类的contains方法,指定包含某个值然后打印输出
stream.filter(F-> F.contains("stream")).forEach(System.out :: print);

map

这个方法可以把流中初始的元素转换成新的流元素,例如泛型中数据类型的转换

List<String> list = new ArrayList<>();
list.add("stream1");
list.add("stream2");
list.add("stream3");
//使用length方法把String类型的流转换为Integer的流
Stream<Integer> stream = list.stream().map(String::length);
stream.forEach(System.out :: print);

skip

skip翻译过来是跳过的意思,在流中可以跳过前边指定的元素,从而执行后面的元素

Stream<Integer> stream = Stream.of(20,30,40,50);
//指定跳过前3个值,流往后执行
stream.skip(3).forEach(System.out :: print);

distinct

distinct是去重(第二声)可避免流中存在重复的数据元素,类似于mysql里的distinct关键字。

Stream<Integer> stream = Stream.of(1,1,1,2,3,4,5);
//使用了distinct方法之后流中重复的1元素将不会多次打印
stream.distinct().forEach(System.out :: print);

limit

这个方法用于限制流中的元素,指定元素的前几个长度并输出。

Stream<String> stream = Stream.of("a","stream","method");
// 指定截取前两个元素,也就是三个字符串的前两个值。
stream.limit(2).forEach(System.out :: print);

count

统计并获取流中元素的个数,此方法是其它类型所以不能进行流方法拼接

Stream<String> stream = Stream.of("this","is","a","count","method");
//调用count方法并用long类型接收
long count = stream.count();
//打印count变量
System.out.println(count);

concat

此方法可以将两个不同的流中的元素合并成一个流进行操作

Stream<String> stream1 = Stream.of("stream01");
Stream<String> stream2 = Stream.of("stream02");
//由于concat被static静态修饰,所以只能由Stream接口去调用
Stream<String> concat = Stream.concat(stream1, stream2);
concat.forEach(System.out :: print);

注意:使用了concat和并流之后不能再调用单独的流进行输出,否则报错

//错误示例
Stream<String> stream1 = Stream.of("stream01");
Stream<String> stream2 = Stream.of("stream02");
Stream<String> concat = Stream.concat(stream1, stream2);
//只调用stream1进行遍历
stream1.forEach(System.out :: println);

其它方法

reduce

reduce主要作用于把Stream流中的元素组合起来做四则运算

它有两种用法:

一种是通过函数式接口用lambda表达式做运算,返回Optional类

Stream<Integer> stream = Stream.of(10,30);
//需要用get方法取出对应流中泛型的对象
Integer get = stream.reduce((K,V) -> K + V).get();
System.out.println(get); //输出为40

还有一种是通过一个初始值做运算

Stream<Integer> stream = Stream.of(10,30);
//设置一个初始值3去和流中的元素做相加,调用Integer包装类的sum方法
Integer sum = stream.reduce(3, Integer包装类的sum方法::sum);
System.out.println(sum);

anyMatch

判断流中是否存在指定的元素,只要有一个条件成立就返回true,返回值为Boolean类型

Stream<String> stream = Stream.of("anyMatch","b","c");
//调用String类的contains方法判断是否包含指定元素,用==和Object的equals也可以判断
System.out.println(stream.anyMatch(k -> k.contains("a")));

allMatch

有一个不匹配的元素就返回true,全部匹配才返回true,boolean类型

Stream<String> stream = Stream.of("allMatch","b","c");
//a不是一个单独的元素,对应此方法返回的是false
System.out.println(stream.allMatch(a -> a.contains("a")));

noneMatch

如果匹配的元素和流中有一个相匹配就返回 false,否则只有都不相同的时候才返回 true

Stream<String> stream = Stream.of("a","b","c");
//流中没有d元素,所以此时才会返回true值
System.out.println(stream.noneMatch(n -> n.contains("d")));

collect

此方法可以将Stream流转换为集合进行操作

List<String> list = new ArrayList<>();
list.add("collect--01");
list.add("collect--02");
list.add("collect--03");
Stream<String> stream = list.stream();
//转换为List集合
List<String> list1 = stream.collect(Collectors.toList());
//转换为Set集合
Set<String> set = stream.collect(Collectors.toSet());
//使用Collectors类调用字符串拼接方法,使用过逗号分割
String collect = stream.collect(Collectors.joining(","));
//输出为:collect = collect--01,collect--02,collect--03
System.out.println("collect = " + collect);
  • 2
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Java 8 引入了一种新的抽象概念 Stream),它使得对数据的处理变得更加简便和高效。Stream 是一种来自数据源的元素队列并支持聚合操作。 Stream API 借助于lambda表达式,极大的提高了Java程序员的生产力,让程序员写出高效率、干净、简洁的代码。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来拆分任务和加速处理过程。 Stream 的特性可以归纳为: - 不是数据结构 - 没有存储元素 - 支持延迟计算 - 支持并行处理 Stream 的操作分为中间操作和终止操作。中间操作会返回一个新的 Stream,我们可以对这个新的 Stream 进行下一步的操作。终止操作则会返回一个最终的结果。 Stream 操作可以分为以下几种: - Intermediate(中间)操作:一个可以后面跟随零个或多个Intermediate操作。其目的主要是打开,做出某种程度的数据映射/过滤,然后返回一个新的,交给下一个操作使用。这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始的遍历。 - Terminal(终止)操作:一个只能有一个 Terminal 操作,当这个操作执行后,就被使用“光”了,无法再被操作。所以这必定是的最后一个操作。Terminal 操作的执行,才会真正开始的遍历,并且会生成一个结果,或者一个 side effect。 Stream API 提供了大量的方法,可以用来完成各种不同的操作,如过滤、映射、筛选、查找、归约等等。这些方法可以分为以下几类: - 转换操作:map、flatMap、filter、distinct、sorted、peek、limit、skip - 聚合操作:forEach、reduce、collect - 匹配操作:allMatch、anyMatch、noneMatch - 查找操作:findFirst、findAny - 统计操作:count、min、max、average、sum Stream API 的使用可以大大简化代码,增加可读性和可维护性。同时,由于它的并行特性,可以有效地提升程序的性能。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值