(最最最齐全的!!)Java Stream API(快速上手)

目录

一、概念

二、Stream的创建

三、Stream流的操作

3.1中间操作

3.1.1map/flatMap

3.1.2filter

3.1.3distinct

3.1.4sorted

3.1.5peek

3.1.6limit

3.1.7skip

3.1.8mapToDouble,mapToInt,mapToLong

3.2最终操作

3.2.1forEach

3.2.2toArray

3.2.3max/min

3.2.4count

3.2.5reduce

3.2.6anyMatch/allMatch/noneMatch

3.2.7findFirst,findAny

3.2.8collect(重要!!!)

3.2.9average


一、概念

Stream主要就是将要处理的元素转换成流,然后通过Stream API对流里面的元素进行操作。比如,把不需要的元素过滤掉,对元素进行分组等。(官方的概念,这里就不介绍了)

Stream中的元素是以optional类型存在的,Optional类是一个可以为null的容器对象。如果值存在则isPresent()方法会返回true,调用get()方法会返回该对象。

二、Stream的创建

Stream的创建有很多种,但我在这里不过多介绍,我把常用的介绍给大家。在日常开发中,这种流式操作可给我们带来很多好处,主要是把集合进行流式处理,例如Map,List,数组,Set等(Collection集合的)。最简单的方法就是这些集合直接调用stream()方法。

List<String> list = new ArrayList<>();
list.add("你");
list.add("我");

//流式处理
list.stream()

三、Stream流的操作

流的操作有两种:

中间操作:一个流可以有0或者多个中间操作,对流进行操作后会返回一个新的流,然后交给下一个操作使用。(中间操作都是惰性的,只有执行到最终操作后,才真正执行,如果没有最终操作,只有中间操作,那么等同于不会执行)eg:filter,map,sorted,提取等。

最终操作:每个流都只能有一个最终操作(如果没有最终操作,中间那些操作根本不会执行),这个最终操作执行完成后,就无法再使用那个流了。eg:(遍历)foreach,(匹配)find,match,(规约)reduce,(聚合)max,min,count,(收集)collect等

对于中间操作和最终操作的理解,下图可以很好理解:

3.1中间操作

中间操作的返回值几乎都是Stream<T>。

3.1.1map/flatMap

map操作就是将流中的每一个元素映射为另外的元素,需要参数Function。flatMap用到的很少,后续用到我再整理。

//流中本来是Student类型,现在通过map转为了String类型

List<String> studentNames = student.stream().map(Student::getName)
                  .collect(Collectors.toList());


//上面代码与下面这段功能一样
List<String> studentNames=new ArrayList<>();
for(Student student:students){
    studentNames.add(student.getName());
}

3.1.2filter

这个操作是用来过滤的,把不符合判断条件的过滤掉,通过测试的会留下了并生成一个新的Stream,接受的参数是推断类型的,返回的是布尔值。

List<Student> studentNames = student.stream()
                .filter(s -> s.getAge() > 18)
                .collect(Collectors.toList());

3.1.3distinct

去重操作,没有参数。直接调用即可

3.1.4sorted

排序操作,默认是从小到大排列。有两个方法,一个是不带参数的,一个是带参数,需要传入一个Comparator<T>。

1.使用不带参数的,那么流中需要比较的元素必须实现Comparable<T>

2.使用带参数的,须传入Comparator<T>,但是ComparatorJava 8之后被打上了@FunctionalInterface,其他方法都提供了default实现,因此我们可以在sort中使用Lambda表达式

3.使用Comparator默认提供的已经实现好的方法引用。例如:comparingInt或者comparing

//带参数

students.stream().sorted((s,o)->Integer.compare(s.getAge(),o.getAge()))
                                  .forEach(System.out::println);;

//使用Comparator提供的方法引用

students.stream().sorted(Comparator.comparingInt(Student::getAge))
                            .forEach(System.out::println);;

3.1.5peek

遍历,和forEach一样,只不过这个是个中间操作


List<Student> sortedStudents= students.stream().distinct().peek(System.out::println).
                                                collect(Collectors.toList());

3.1.6limit

可以理解为裁剪,接收long类型的参数,通过limit后的元素会剩下min(n,size)个元素,size表示流中元素个数,n表示参数(保留前面元素)

//只留下前6个元素并打印
students.stream().limit(6).forEach(System.out::println);

3.1.7skip

表示跳过多个个元素,只不过这个是保留后半部分的元素。

//跳过前3个元素并打印 
students.stream().skip(3).forEach(System.out::println);

3.1.8mapToDouble,mapToInt,mapToLong

将流中的元素通过一个映射转换为double类型的值,并返回一个DoubleStream。这个DoubleStream可以进行一系列针对双精度浮点数的操作,如求和,平均值,最大值,最小值等。

mapToInt和mapToLong使用和mapToDouble类似。

EG:mapToDouble(Integer::doubleValue)将整数流中的每个整数通过Integer::doubleValue方法引用转换为双精度浮点数

3.2最终操作

每个流都只会有一个最终操作,只有通过最终操作后,流才算真正被处理,可以理解为最终操作就是把流转换为一个容器。

3.2.1forEach

//遍历打印
students.stream().forEach(System.out::println);

3.2.2toArray

默认toArray()会返回一个object[]==》不传参数的时候

可以返回指定类型的=》传参数了

//传参数的示例

 Student[] studentArray = students.stream().skip(3).toArray(Student[]::new);

3.2.3max/min

找出最大或者最小元素,必须传入Comparator

        Optional<Double> op = priceList.stream()
                .max(Double::compareTo);
        Optional<Double> op1 = priceList.stream()
                .min(Double::compareTo);

3.2.4count

返回流中元素的数量

long  count = students.stream().skip(3).count();

3.2.5reduce

归纳操作,把流中的各个元素结合起来。

带一个参数--》只传入相关表达式,返回的是Opeational

带两个参数--》传入一个起始值和表达式,返回一个确定的值

List<Integer> integers = new ArrayList<>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        
long count = integers.stream().reduce(0,(x,y)->x+y);

3.2.6anyMatch/allMatch/noneMatch

测试是否有任意元素、所有元素、没有元素匹配表达式,返回布尔类型

 boolean test = integers.stream().anyMatch(x->x>3);

3.2.7findFirst,findAny

不接受任何参数,返回流中第一个元素和返回流中任意一个元素

int foo = integers.stream().findAny().get();

3.2.8collect(重要!!!)

它可以传入一个参数和传入三个参数,传入一个参数的情况使用率很高,所以我这就先只介绍一个参数的时候,后续可能再补充三个参数的。

一个参数的时候,我们直接传入Collectors中的方法引用即可。

例如toList()默认生成的是ArrayList(只是把元素收集起来了,并不会改变原来的类型,如果想改变原来的类型,需要通过map去改变),toSet()默认生成的是HashSet,toMap,groupingBy()等。

toList默认生成的是ArrayList,toSet默认生成的是HashSet,如果想要指定其他容器,可以如下操作:

 students.stream().collect(Collectors.toCollection(TreeSet::new));

对于groupingBy()的使用:

可以有三个参数:

1.分组按照什么分类

2.分组最后用什么容器保存(可以忽略,默认提供的是HashMap)

3.按照第一个分组后,对应的结果应该如何收集

也可以多字段分组,groupingBy()嵌套groupingBy()即可

Collectors.groupingBy(ProjectStatisticsVO::getProjectClassfication, Collectors.groupingBy(....,....));

Collectors还有一个方法挺好用的:

 joining方法用于将流中的字符串元素连接成一个字符串,可以将流中的字符串按照指定的分隔符拼接在一起,也可以添加前缀和后缀。

collect(Collectors.joining())//这个直接将字符串拼在一起,没有分隔符
如:hello  world   拼接完后是helloworld

collect(Collectors.joining(", "))
拼接完是hello,world


collect(Collectors.joining(", ", "[", "]"))
拼接完是[hello,world]

3.2.9average

是DoubleStream的一个终端方法(由mapToDouble等操作生成),用于计算DoubleStream中所有元素的平均值。返回一个OptionalDouble类型的值,用于可能包含或者不包含双精度浮点数的情况。(不用传参)

这篇文章总结的不太齐全,等我再用到没用过的就慢慢补充进来,这个stream流很好用,很方便,但是只看这些概念却不行,得多加练习。 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值