前言一、什么是流?二、创建流
语法:1.将值转换为流(例子,一般用于筛选数据)2.将集合转化为流3.将数组转化为流4.无限流4.最后举个例子
总结
JDK 8引入了全新的Stream API。其允许以声明性方式处理数据集合。更像可以遍历数据集的高级迭代器;更重要的是,流还可以透明的并行处理数据(可以更好的利用多核心处理器),而不需要任何多线程代码。
前言
为什么使用流?
几个单词就能把迭代器的活全干了,不用管是什么数据类型,直接遍历。
定义: 流是从支持数据处理操作的源,生成的元素序列
特点:流操作有两个重要的特点:流水线和内部迭代
一个图说明其特点(如果看不明白,等看完这篇文章,回头看,就懂了)
相关包:
java.util.stream包,存放的是Stream接口和针对其进行的操作类
java.util.function包,存放的是在Stream API中用的函数式接口
Stream流的操作概述:
主要分为中间操作和最终操作,中间操作是指返回的Stream本身,中间操作之后还可以跟上其他Stream操作。比如:stream.filter().map().skip(),中间操作是可以合并的。最终操作是指最终返回一特定类型的计算结果,由于由于其并不产生新的集合,所以有时也称其为惰性求值方法。
注意:除非流水线上触发一个终端操作,否则中间操作不会真正执行。这是因为大部分中间操作可以合并(循环合并),所以可以在终端操作时一次性全部处理
Stream的特性:
1. stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
2. stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
3. stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
注意:Stream流的创建需要指定一个数据源,可以是List或者是Set,也可以是数组,但是不能是HashMap,因为其不支持Collection接口。
语法:Collection.stream() 或者 Collection.parallelStream() 来创建一个流 注意:第二个是用在多核上的1.将值转换为流(例子,一般用于筛选数据)
Stream.of()
利用方法参数生成新的stream。Stream是个接口,但在java 8中接口中可以拥有默认方法和静态方法,of()就是个静态方法
代码如下(示例)
代码测试1 Streamstream = Stream.of("git", "github.com", "gitlab"); stream.forEach(System.out::println); 代码测试2 Stream stream=Stream.of("git","github.com", "gitlab"); stream.skip(1).forEach(System.out::println);//skip(1)指跳出第一个数据 代码测试3 Stream stream=Stream.of("git","github.com", "gitlab"); //value->是lamda表达式,toUpperCase是将结果转化为大写 stream.skip(1).map(value>value.toUpperCase(Locale.ROOT)).forEach(System.out::println); 测试4 Stream stream=Stream.of("git","github.com", "gitlab"); //skip(1)跳过第一个数据,value->是lamda表达式,toUpperCase是将结果转化为大写,filter是过滤,在这里指过滤含有u的单词,还可以用indexof(String string)来进行过滤 stream.skip(1).filter(value->value.contains("u")).map(value->value.toUpperCase(Locale.ROOT)).forEach(System.out::println);
测试1结果:
测试2结果:
测试3结果:
测试4结果:
stream()
java.util.Collection 接口利用默认方法实现了stream()方法。任何实现了Collection接口类的实例都可以调用stream()方法,用以将集合转化成流。
代码如下(示例):
//对比以下流和Iterator 对集合的遍历
List list=new ArrayList<>();
list.add(1);
list.add("我是灰太狼");
list.add("我是喜羊羊");
Stream steam=list.stream();
steam.forEach(System.out::println);
// Iterator iterator= list.iterator();
// while(iterator.hasNext()){
// System.out.println(iterator.next());
//}
//或者直接list.stream.forEach(System.out::println),上面那么写是更好的解释过程
测试结果:
除了下面方法外还可以用Arrays.stream()将数组转为流
String[] array = {"git", "github.com", "gitlab"};
Stream stream = Stream.of(array);
stream.forEach(System.out::println);
测试结果
Stream.iterate(n,lambda);
List list=new ArrayList();
list.add("熊大");
list.add("熊二");
Stream.iterate(0,i->i+1).limit(list.size()).forEach(i->System.out.println(list.get(i)));
//iterate():0为初始值;i+1为增量,此时产生的是无限流
//limit()://限制流的范围为list集合的长度
测试结果
Stream.generate(lambda)
List list=Stream.generate(()->Math.random()).limit(10)//随机产生生成数
.map(value->{
var stringValue=value.toString();
return stringValue.substring(2,4);
}).collect(Collectors.toList());
System.out.println("生成了"+list.size()+"个两位的随机数,具体数字如下:");
list.stream().forEach(System.out::println);
//map()方法,是一个中间操作,其逻辑是对流中的每个元素进行一组操作。
//collect()方法,是一个最终操作。将数据流缩减为一个值的归约操作。这个值可以是集合、映射,或者一个值对象。
4.最后举个例子
String[] arrays={"1","2","4","hello","world","tom","4"};
List list= Arrays.stream(arrays)//把数组转换成流
.distinct()//去重(没有参数)
.filter(item->!item.substring(0,1).equals("h"))//过滤元素
.map(item->item.toUpperCase())//操作迭代中的元素
.collect(Collectors.toList());//把流转换成List 集合
list.forEach(System.out::println);
Case2:
int[] arrayInt={1,2,3,4};
int sum=Arrays.stream(arrayInt).skip(2)//跳过前两个数
.reduce(0,(prev,next)->prev+next);//把元素迭代相加
System.out.println("sum:"+sum);
测试结果1
测试结果2:
总结
关于流的学习还有很多很多,更是涉及到了不少的Lamda表达式
下面总结几个常用的流式操作的函数吧。
Stream.iterate(n,lambda):实际上是普通for循环的StreamAPI写法
Stream.foreach():是一个最终操作,其处理的逻辑是对流中的所有数据进行逐一操作
filter() : 是一个中间操作,其逻辑是过滤掉不符要求的元素,常用的有indexof()和contains()
map(): 是一个中间操作,其逻辑是对流中的每个元素进行一组操作
collect(): 是一个最终操作。将数据流缩减为一个值的归约操作。这个值可以是集合、映射,或者一个值对象。
reduce(): 是一个是最终方法,其的功能是从一组元素中生成一个值sum()、max()、min()、count()等都是reduce操作,将他们单独设为函数只是因为常用



