![从企业级开发到云原生微服务:Spring Boot实战](https://wfqqreader-1252317822.image.myqcloud.com/cover/257/33831257/b_33831257.jpg)
2.5 Stream
前面在 “函数接口”中执行的演示都是手动调用函数接口中的函数(如test()、apply()等)执行的,本节介绍的Stream就是“函数接口”的使用环境。
2.5.1 Stream简介
Stream是用声明式的方式来操作数据集合的一个Java API。一般来说,可以从数据源(集合类、数组)获得Stream,而Stream就是数据序列,我们可以对数据序列进行各种数据处理操作(过滤、转换、排序、查询等)。
很多Stream数据处理操作方法的返回值还是一个Stream,此时可以对新的Stream再进行数据处理操作,这意味着可以把多个数据处理操作“串”成一条大的处理管道(pipeline)。返回值还是Stream的数据处理操作可以称为中间操作。中间操作并没有对数据做运算处理,而是对数据处理的方式做了声明。
除此之外,还有另一类操作,即在Stream进行一些管道处理后,把Stream转换成所需结果的数据操作,这些操作可以称之为终结操作。
在进行Stream开发时只需以下三步。
(1)从数据源获得Stream。
(2)中间操作:组成处理管道。
(3)终结操作:从管道中产生处理结果。
2.5.2 获得Stream
(1)从普通值获取:Stream.of。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_34_01.jpg?sign=1739276607-pfmn5XKLCg8CCYiKGuFesh5ccFKjKw93-0-97d5eaf371fda4638057c3797d869bfc)
(2)空Stream:Stream.empty。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_34_02.jpg?sign=1739276607-QGavMahPQGGejs9ZTYBl63S33asRINLJ-0-5cab5cf92154e82dc791f00a5625e585)
(3)从空值中获取:Stream.ofNullable。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_34_03.jpg?sign=1739276607-fJvpEYz0NJc7UYXl8jUDbzqka4kxiQl6-0-cad4e6f4f1a3c26bc9d9a72bc4a40093)
(4)从数组中获取:Arrays.stream。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_34_04.jpg?sign=1739276607-jOdMQTU0ObjPvGmTXzfq2NXCTFjXygeF-0-ec04ac57176a1f3157ac8178e144246d)
(5)来自文件:Files类的静态方法。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_34_05.jpg?sign=1739276607-G2NVoRJ1YAOCZLz57kleU9jg5RlTLBPO-0-73b666a9e5510ce48bf19be4b375b333)
(6)来自集合类:Collection、List和Set。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_01.jpg?sign=1739276607-mYqkvdSA5qLRANVngN6IGDJlCxpdIMTh-0-54e90b207e1dd88639686f97846176bf)
(7)使用建造者模式(builder pattern)构建:Stream.builder。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_02.jpg?sign=1739276607-wjHsRSyGYi0dUuKW1siEzX1yHr7pSGSi-0-bd0aa239792e93d43e8cafa4d2a56a8f)
(8)来自函数:Stream.generate和Stream.iterate。
◎Stream.generate接收一个Supplier函数接口作为参数,且产生的Stream是无限的,使用时请限制数量。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_03.jpg?sign=1739276607-DxhDAe6NPudiSpBSQgWMP3vD7GnUaAON-0-d4c016a7185539e6a95758833f23cfa6)
◎Stream.iterate接收的第一个参数是起始值,第二个参数是UnaryOperator,产生的Stream是无限的,需要限制数量。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_04.jpg?sign=1739276607-Ar4jYy1Ogyx3HpfrIg85bys43wA829Iy-0-7d29a0c8bee0cf3279d08ba11dc5c6c5)
(9)原始数据类型的Stream(只包含某类原始数据类型的Stream):IntStream、LongStream和DoubleStream的静态方法。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_05.jpg?sign=1739276607-RI04pZbtMsjn5nuv5xwe08WwGezibQ8A-0-f1ad142e52125a3f42447f15ef0f8c53)
(10)来自字符串。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_06.jpg?sign=1739276607-zLxiFbjaKSbjR2Q2X9HX9EKmYvWf8vFo-0-17d1df15bb368adf837b4d13e46ee04a)
(11)来自Optional。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_07.jpg?sign=1739276607-LR8JhDUYLGkW9f4E6fxkxCGQXLwHPSn5-0-2db78813fceefdabbc12a4487be65c4c)
2.5.3 中间操作
中间操作(Intermediate Operations)不会得到最终的结果,只返回一个新的Stream。中间操作接收函数接口作为参数,可以使用“Lambda表达式“和“方法引用”作为实现。
1.演示所用Stream
从集合类获得Stream。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_35_08.jpg?sign=1739276607-p3mdA8Ejs5k7z29ceCKhoxGsvZbj2s6Z-0-cc25cff15f4481df3b6e1d6d8b8a572c)
2.过滤
(1)filter方法。
Stream的过滤主要是通过Stream的filter方法实现的,filter方法接收一个Predicate函数接口作为参数,Predicate接受一个参数T,返回值为boolean类型。当数据运算的结果为true时,数据保留。下面过滤出性别为男的数据。为了演示,先引入forEach这个终结操作来展示filter方法操作的结果。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_36_01.jpg?sign=1739276607-ZezfGw1E5KYFuDywoRawsXH6vhNhU9KV-0-c00bdc26b15e2bff10f0251711acd7cc)
除Lambda表达式可以作为函数接口的实现外,方法引用也可以作为函数接口的实现。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_36_02.jpg?sign=1739276607-3xElrqRNPt8BYYtezO7PZFSVxjHfCMxb-0-59f3de8981aec8341009026d4f865faa)
方法引用这种形式极大地提高了代码简洁性和可读性。这里的方法引用方式属于“引用特定类的任意对象的方法”,即引用的是Stream中任意对象的方法。
(2)distinct方法。
可以使用distinct方法过滤掉相同的数据,只留下唯一一个。当然,前提是需要覆写Person类的equals和hashCode方法来标识数据是相同的。
首先用Person类覆写equals和hashCode方法。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_36_03.jpg?sign=1739276607-3oMZ11Q0hKzKAlWJ9hzGqs7LnsQAXfHt-0-297c66f0baae3f0adeec92043d18c17c)
然后Stream直接调用distinct方法,返回一个新的Stream。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_36_04.jpg?sign=1739276607-DkUYKKKCX1QkXGIdxLAzEzlABIg4ZHGz-0-f9207f7505d0ee658467ccd7af71a949)
(3)中间操作管道。
当然,可以将filter和distinct操作“串”成操作管道,例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_37_01.jpg?sign=1739276607-NDVYqZGhpvsIRktZ7hp7RvYrZYbp0XA3-0-e9afa66b30cd115651f7ddf69be724e9)
3.转换处理
Stream API通过map和flatMap方法对已有数据进行转换处理。
(1)map方法。
map方法的参数是一个Function接口,接收一个参数T,返回值类型为R。map方法得到的新Stream是包含R类型的数据,例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_37_02.jpg?sign=1739276607-hFruer8rBPj5CKNYKIjZHZCagBRKRkAy-0-7da2faecd1d1a7d87d392308b3a0e230)
入参为Person类型的person,返回值是字符串。新的Stream包含的数据类型为String,也可使用方法引用简写成:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_37_03.jpg?sign=1739276607-J0QBl5XVT2U7mCe2BPOgEK6jUzZD7520-0-d06447c0e8c9294c6b21826dcfb5178c)
也可以链起多个map方法的管道,例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_37_04.jpg?sign=1739276607-Gnwba3jrJ3ha1IKQkHHv1aqaVqeubkfD-0-ea4ef88e2ac2d93ad04a27230024aa68)
(2)flatMap方法。
flatMap方法用来处理Stream嵌套的问题,例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_37_05.jpg?sign=1739276607-lHY8CLewavSMbsTaKMOS4qkU9waGQbKr-0-58f05829b55a2f458d6020157c69e51f)
a.此时flatMap方法将Stream中包含的List转换成2个Stream,并将两个Stream合并成1个Stream。
b.获取合并的Stream,打印出来的结果是people1和people2列表里的所有Person实例。
若采用map处理,则需要处理嵌套的Stream。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_37_06.jpg?sign=1739276607-sN7YmoOQIYgx5hCu4YryGaRL4L4ENl0H-0-3529a45ec62c869bddce1230b73c176c)
(3)原始数据类型方法。
Stream中有很多针对原始数据类型的转换处理方法:mapToInt、mapToLong、mapToDouble、flatMapToInt、flatMapToLong和flatMapToDouble。例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_01.jpg?sign=1739276607-DIvLPJOWLANpAvvnehF3sAwPjinWGnZC-0-2728f38305f90649b0f5d5dafc900efd)
4.其他操作
(1)skip:忽略前n条数据。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_02.jpg?sign=1739276607-oEu2sCIWv8VVREoufWIXJtszfclVFWkR-0-3bd4c603cf7fb58c82e3aa4850f7e766)
(2)limit:限制只需要前n条数据。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_03.jpg?sign=1739276607-1jKww1kylcrFP8JyYTfAn7wJkC9nuDrY-0-4b7c3eb759c003343a1d987243f39f34)
(3)sorted:将数据排序。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_04.jpg?sign=1739276607-cd7g51RxW39zRFeYDxQSYUbcffHTYKdz-0-f971ecc4b11a27b25743877aa2abb647)
2.5.4 终结操作
1.聚合操作
(1)count:获得Stream中的数据数量。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_05.jpg?sign=1739276607-voxpwEjyOUmgei9AnNpBj3Dg6g65vnGL-0-cff5e92e474715c94b13c2daa6ff2f7c)
(2)max:获得Stream中按照规则约定的最大值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_06.jpg?sign=1739276607-gE4lK6e320ZzX8r9mOi8wI4I67FkN3nS-0-5ba3c30bede0e169c17287d38d87097b)
(3)min:获得Stream中按照规则约定的最小值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_07.jpg?sign=1739276607-KJuFt9DOylGyyLJ7V064mZtKTIPVRbK6-0-e3cbafefea7f5506ffe5c57ae32b8420)
2.循环
forEach:对Stream中的数据进行循环处理,forEach的参数是Consumer函数接口,只接收参数,没有返回值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_08.jpg?sign=1739276607-IiuIdFthu1IdSafK2UcDoodIHX5924Au-0-089a983c972d87f68a50bee76c38d844)
打印peopleStream中的每个Person对象。
3.匹配
(1)allMatch:Stream数据是否全部匹配,返回布尔值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_09.jpg?sign=1739276607-RKHhXZ9cy1q3LjDjcZ0I9MFPLMxp1ETJ-0-6a191ca5a2a7f8b786344ed5dd521cb2)
(2)anyMatch:Stream数据是否有任意匹配,返回布尔值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_38_10.jpg?sign=1739276607-Bh47vaAHffhqgJ2R4zxTXk4y6pRkCkr7-0-22be0283dbf16482af5a4c42402814d2)
(3)nonMatch:Stream数据是否全部不匹配,返回布尔值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_39_01.jpg?sign=1739276607-P0cjDmomXbv1GFVJk80veRDORpgaXTnK-0-83c2000390e842c2a829a7b52d917dbb)
4.查找
(1)findAny:获得Stream中的任意数据。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_39_02.jpg?sign=1739276607-4QKH3ijLVuJOiP69x9m8y5L0JcuR59u9-0-228ba8f5665e86e22381aa2a7a43f205)
findAny的返回值是Optional,会在后面讲到,使用Optional的get方法可以获得数据。
(2)findFirst:获得Stream中的第一条数据。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_39_03.jpg?sign=1739276607-hu6pUwwiVcuxAylwROwk65Mlse9dHOca-0-49a0f98958316e1c5bb0dc40b4ac11d4)
5.获得数组
toArray方法可以将Stream中的数据转换为Object数组,例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_39_04.jpg?sign=1739276607-xrDgwNsZablO0Y7gsB2AnCdteyjwRa8d-0-9b796c2699c9a613702ed0eb2c8456c6)
6.reduce方法
Stream的reduce方法可以进行累计的聚合操作。reduce方法的参数主要分为两个:
(1)第一个是初始值(可选)。
(2)第二个为累计方法:按步两两计算,计算的结果作为下一步累计计算的开始值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_39_05.jpg?sign=1739276607-uzQ7TH2SZLHsXfgmWXTbASoqTIAdqf4O-0-c46c6f7a8ec0fed1b40a9f57027849f6)
a.数据有1、2、3。第一步,计算1+2=3;第二步,将第一步得到的结果3与3相加,得到6。
b.初始值为10,数据有1、2、3。第一步,10+1=11;第二步,11+2=13;第三步,13+3=16。
c.数组有1、2、3。第一步,计算1×2=2;第二步,将得到的结果2与3相乘,得到6。
d.初始值为10,数据有1、2、3。第一步,10 ×1=10;第二步,10×2=20;第三步,20 ×3=60。
e.数据有1、2、3。第一步,比较1和2大小;第二步,将第一步较大值2与3相比,得到最大值为3。
f.初始值为10,数据有1、2、3。第一步,比较10和1。第二步,将第一步较大值10与2相比,较大值为10;第三步,将第二步较大值10与3相比,得到最大值为10。
g.数组有1、2、3。第一步,比较1和2大小;第二步,将第一步较小值1与3相比,得到最小值为1。
h.初始值为10,数据有1、2、3。第一步,比较10和1;第二步,将第一步较小值1与2相比,较小值仍为1;第三步,将第二步较小值1与3相比,得到最小值为1。
7.collect方法
Stream中的 collect方法是终结操作中功能最丰富的一个方法,它接收一个java.util.stream.Collector参数,Collector参数指定了Stream转换成值的方式。Java预先定义了大量的Collector参数来解决常见问题。collect方法可通过java.util.stream.Collectors类的静态方法构造。
Collectors的静态方法主要分为以下几类。
(1)转换成集合类。
◎Collectors.toList()。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_40_01.jpg?sign=1739276607-BahpoYS1geJDRP7vFhhcyontohZllb5F-0-2dbdf4f750f506c8f8f3e4aebf7789f8)
◎Collectors.toSet()。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_40_02.jpg?sign=1739276607-MCMFZT9sznwBTCYcBSgUSHhxWpRkbUU5-0-7f2e50472f90995dd77b14f890319527)
◎Collectors.toCollection(集合类型)。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_40_03.jpg?sign=1739276607-Oc7RCBuqzHqjGRKQoxUA0MaUTVrIJH0l-0-89127052663222f4d70c487cfaed9497)
(2)转换成String。
◎Collectors.joining():用来给Stream中的字符串数据指定分隔符、前缀和后缀,然后连接成一个字符串。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_40_04.jpg?sign=1739276607-gOcVFBQp0mulLQnMhWGllAII4h0ozaaL-0-f411bcfb43f0feab805ffd6ba3ff4c92)
第一个参数以“,”为分隔符,第二个参数以“[”为前缀,第三个参数以“]”为后缀,字符串streamToString为“[wyf,www,foo,bar]”。另外,joining还有一个方法是只有分隔符,没有前缀和后缀。例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_40_05.jpg?sign=1739276607-AOzZhDfuurXIDLo6zuaHOPwngWfobuic-0-3c4f69cfa9be07f7bddf8445874f5926)
字符串streamToStringOnlyDelimiter经转换后为“wyf,www,foo,bar”。
(3)聚合操作。
◎Collectors.counting():Stream中的数据数量。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_01.jpg?sign=1739276607-clQ6VdiojuRpMZarMLJXYHPwPr5ou6hz-0-4819e54e479ba4135e3b1cc3a67392b5)
◎Collectors.maxBy():Stream中的数据按照某种规则约定的最大值,下面是比较字符串长度的最大值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_02.jpg?sign=1739276607-R7RkO6QUjj3DwsFkfP8Mj4ZpxWo1zGt8-0-33edad1a05de94c07cdc5b33a6f6aad4)
◎Collectors.minBy():Stream中的数据按照某种规则约定的最小值,下面是比较字符串长度的最小值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_03.jpg?sign=1739276607-B2HNRCr58qNHgHJ0xUg1p0SfETfJDmI4-0-a7b57c00fa9c284f3a9100294e75c674)
◎Collectors.averagingInt/Long/Double:求Stream中的数据的平均值,下面是求字符串长度的平均值。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_04.jpg?sign=1739276607-UH2zBtP5Oj4vMU4tvKWhzGOQSZm6nIBN-0-88c60e13b4609b0addbeb729fb9d7afb)
◎Collectors.summingInt/Long/Double:求Stream中数据的和,下面是求字符串长度的和。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_05.jpg?sign=1739276607-4fmLkU8nkWRmpD7mhVum0LnZJbgzW4zj-0-395afe2b17ac011ba06a98a072ef0986)
◎Collectors.summarizingInt/Long/Double:汇总Stream数据情况,包括平均值、求和、最大值、最小值和数量,所有值都包含在返回值类型IntSummaryStatistics(LongSummaryStatistics/DoubleSummaryStatistics)中。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_06.jpg?sign=1739276607-O9oQOG0yAPWTJQ0XEN26e7Eope3awWnE-0-03b25a4dbb0e1820a525134f8e92a58a)
(4)转换成Map。
◎Collectors.toMap():toMap方法将Stream转换成Map。toMap方法有两个参数:keyMapper(Map实例key生成方式)和valueMapper(Map实例value生成方式)。这两个参数的类型都是Function接口。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_41_07.jpg?sign=1739276607-KGMXIQ2uY0n2tm2AuFBRJ8YHRxZIHpwo-0-ca91a8b9f20c1c0505947fbe6b5e886f)
本例将字符串作为key,Function.identity()是参数keyMapper,它返回的是输入参数(字符串)String::length是参数valueMapper,它返回的是字符串长度。转换后Map将字符串作为key,将字符串长度作为value。
◎Collectors.groupingBy():按照特定功能处理分组,接收一个Function接口。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_42_01.jpg?sign=1739276607-kJZPB5gzqyIRsvEzBFkFGUejdIupcSYW-0-1e3a4f1df75981db3c627892bf47e964)
按照字符串的长度进行分组,长度相等的分到一组(List<String>),字符串长度为 key。因此上面的例子可分为两组,第一组key为3,List<String>的值是:wyf、www;第二组key为6,List<String>的值为:foobar和barfoo。
◎Collectors.partitioningBy():partitioningBy是一种特殊的 groupingBy方法,它接收Predicate作为参数,只将数据分成false和true两组。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_42_02.jpg?sign=1739276607-6cYHe7kCUaR7piqnkrYKT4i3VrIWlUhw-0-9f533e77e41d67721a64257f9f62b3dc)
判断条件是字符串长度是否为6,字符串长度不为6的进入key为false的分组,字符串长度为6的进入key为true的分组。
(5)Collectors.collectingAndThen:collect执行后将值再进行转换。
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_42_03.jpg?sign=1739276607-Sl41SC1AQWZcrvXtjWSDOL4WBRDx2Z43-0-75036cd300c9c23691fa5d78a139b680)
将Stream转成List(Collectors.toList())后,接下来是获取List的大小(List::size)。
为了演示,前面所有例子全部使用Collectors静态方法,实际上,通过静态方法导入可以让代码更简洁。例如:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_42_04.jpg?sign=1739276607-nWHNyAPR9gt6ntg51BF9dFiuKGSEwotf-0-607f4a581e7a8bb9650bec2ef82a1a78)
代码可以写成:
![](https://epubservercos.yuewen.com/E5E2EB/18096059808236406/epubprivate/OEBPS/Images/37792_42_05.jpg?sign=1739276607-gfhEl7SCvMG5r8C13jrm4edkT85b42ci-0-d7ccce27da2652b23f92f7bd00832c41)