本文目录
- 1.创建IntStream流(IntStream中的静态方法:of / builder/ range / rangeClosed / generate / iterate)
- 2.filter
- 3.map
- 4.flatMap
- 5.peek
- 6.mapToObj / mapToLong / mapToDouble / asLongStream / asDoubleStream
- 7.forEach / forEachOrdered
- 8.distinct
- 9.sorted
- 10.limit
- 11.skip
- 12.reduce
- 13.sum / min / max / count / average / summaryStatistics
- 14.anyMatch / allMatch / noneMatch
- 15.findFirst / findAny
- 16.sequential / parallel
- 17.iterator
- 18.boxed
- 19.toArray
- 20.close / onClose
- 21.collect
本章节我们提供一些 Java 8 中的
IntStream
、LongStream
和DoubleStream
使用范例。IntStream、LongStream 和 DoubleStream 分别表示原始 int 流、 原始 long 流 和 原始 double 流。
这三个原始流类在
java.util.stream
命名空间下,并提供了大量的方法用于操作流中的数据
,同时提供了相应的静态方法来初始化它们自己
。
本文仅介绍
IntStream
的方法,LongStream/DoubleStream 的使用同 IntStream 一致,此处不再过多介绍。
1.创建IntStream流(IntStream中的静态方法:of / builder/ range / rangeClosed / generate / iterate)
创建IntStream流的几种方式,如下:
1. IntStream.of()方式
// 支持一个参数,也支持可变参数 IntStream intStream = IntStream.of(1); IntStream intStream = IntStream.of(1,2,3,4,5,6,7);
2. IntStream.builder()方式 (了解即可)
// 1.可以使用add()方法添加元素 IntStream builderStream= builder.add(111).add(222).add(333).add(444).build(); // 2.也可以使用accept()方式添加,add()方法底层也是通过accept()方式添加的(这种方式不支持链式调用,此处了解一下即可) IntStream.Builder builder = IntStream.builder(); builder.accept(3); builder.accept(4); builder.accept(5); IntStream builderStream = builder.build();
3. IntStream.range()、IntStream.rangeClosed()方式
将指定范围内的元素都添加到int流中
range()前者不包含最后一个元素,即:前闭后开区间;
rangeClosed()后者包含,即:前闭后闭区间;// 支持一个参数,也支持可变参数 IntStream range = IntStream.range(1, 100); // 返回 1,2,3,4,......,99 IntStream range = IntStream.rangeClosed(1, 100); // 返回 1,2,3,4,......,99,100
4. IntStream.generate()方式 (了解即可)
// 1.这种方式,是无限连续的流,会源源不断的生成100内的随机数(持续不断输出) IntStream generate1 = IntStream.generate(() -> new Random().nextInt(100)); // 2.使用limit()会限制流中元素的数量 IntStream generate1 = IntStream.generate(() -> new Random().nextInt(100)).limit(6);
5. IntStream.iterate()方式
指定生成int流中int元素的生成函数,前者的生成函数没有入参,后者会将前一次调用结果作为下一次调用生成函数的入参
第一个参数seed,就是第一次调用生成函数的入参// 规则:生成2的幂次方int流 // 根据指定规则,生成一串int流(使用iterate()方式,也是无限连续的流,需使用limit()来限制元素的数量) IntStream intStream11 = IntStream.iterate(1,x->{ int a = 2 * x; return a; }).limit(6); // 简写: IntStream intStream11 = IntStream.iterate(1,x->2 * x).limit(6);
6. IntStream.concat()方式 (将两个int流合并成一个流)
// 将A流和B流合并,生成新流 IntStream range1 = IntStream.range(1, 5); // A流 IntStream range2 = IntStream.range(10, 15); // B流 IntStream concat = IntStream.concat(range1, range2); // 合并后的流
2.filter
filter() 方法,用于过滤数据,返回符合过滤条件的数据,是一个非终结方法。
我们可以通过 filter() 方法将一个流转换成另一个子集流。该接口接收一个 Predicate 函数式接口参数(可以是一个 Lambda 或 方法引用) 作为筛选条件。因为 filter() 是一个非终结方法,所以必须调用终止方法。
示例如下:
@Test
public void test(){
// 获取1-9的int流
IntStream intStream = IntStream.range(1, 10);
// 通过filter方式过滤掉小于5的数字,并输出
intStream.filter(x->x>5).forEach(System.out::println);
}
输出结果:
6
7
8
9
3.map
IntStream 中的map()方法用于对流中的所有元素执行某个修改操作
,这与 Stream 中的map()方法有所不同。Stream 中的map() 方法,参考:JDK8新特性(三):集合之 Stream 流式操作
@Test
public void test02() {
IntStream intStream = IntStream.range(1, 10);
// 使用map(),将流中的数据*2返回
intStream.map(new IntUnaryOperator() {
@Override
public int applyAsInt(int value) {
return 2 * value;
}
}).forEach(System.out::println);
// 简写
intStream.map(o -> 2 * o).forEach(System.out::println);
}
输出结果:
2
4
6
8
10
12
14
16
18
4.flatMap
flatMap() 方法同 map() 方法。
区别在于:flatMap() 方法的返回值是一个 IntStream 而非 int 值,可以在返回的IntStream 中包含多个元素,flatMap() 方法最终返回的 IntStream 是将每次调用 flatMap() 方法返回的 IntStream 合并后的结果
。
@Test
public void test03() {
IntStream intStream = IntStream.range(1, 10);
// 使用flatMap(),将流中的数据*2返回
intStream.flatMap(new IntFunction<IntStream>() {
@Override
public IntStream apply(int value) {
return IntStream.of(2 * value);
}
}).forEach(System.out::println);
// 简写
intStream.flatMap(o -> IntStream.of(2 * o)).forEach(System.out::println);
}
输出结果:
2
4
6
8
10
12
14
16
18
5.peek
介绍:该方法会生成一个包含原 Stream 的所有元素的新 Stream,同时会提供一个消费函数(Consumer实例),新Stream每个元素被消费的时候都会执行给定的消费函数;
存在此方法的目的,主要是为了在您需要的地方支持调试,查看元素流过管道中特定点的情况
主要用于开发过程中调试使用!!!
@Test
public void test04() {
IntStream intStream = IntStream.range(1, 10);
long count = intStream.filter(x -> x > 5)
.peek(val -> System.out.println("是否>5:" + val))
.count();
System.out.println("过滤后总数为:" + count);
}
输出结果:
是否>5:6
是否>5:7
是否>5:8
是否>5:9
过滤后总数为:4
6.mapToObj / mapToLong / mapToDouble / asLongStream / asDoubleStream
1.mapToObj:将 int 流转换成
其他类型
的流 (其他类型:可以使自定义对象类型,也可以是List类型等)
2.mapToLong:将 int 流转换成Long
类型的流,不可指定返回值规则 (挺简单的,此处不做demo演示)
3.mapToDouble:将 int 流转换成Double
类型的流,不可指定返回值规则 (挺简单的,此处不做demo演示)
4.asLongStream:将 int 流转换成Long
类型的流,该方法遵循标准的int到指定类型的转换规则,不能指定规则,比如说将int流对象先 乘以2再返回 (挺简单的,此处不做demo演示)
5.asDoubleStream:将 int 流转换成Double
类型的流,该方法遵循标准的int到指定类型的转换规则,不能指定规则,比如说将int流对象先 乘以2再返回 (挺简单的,此处不做demo演示)
// mapToObj()方法演示
@Test
public void test06() {
IntStream intStream = IntStream.range(1, 10);
// mapToObj():将int流转换成Person对象
intStream.mapToObj(val -> new Person(val, "Mary" + val))
.forEach(System.out::println);
}
// Person类
public class Person {
private int id;
private String name;
public Person(int id, String name) {
this.id = id;
this.name = name;
}
@Override
public String toString() {
return "Person{" +
"id=" + id +
", name='" + name + '\'' +
'}';
}
}
// mapToLong / mapToDouble / asLongStream / asDoubleStream()方法演示
// 一个stream流只能被消费一次,以下是伪代码,会报错。
@Test
public void test07() {
IntStream intStream = IntStream.range(1, 10);
// mapToLong()方法(可指定返回值规则)
intStream.mapToLong(val -> 2 * val).forEach(System.out::println);
// mapToDouble()方法(可指定返回值规则)
intStream.mapToDouble(val -> 2 * val).forEach(System.out::println);
// asDoubleStream()方法(不可指定返回值规则)
intStream.asDoubleStream().forEach(System.out::println);
// asLongStream()方法(不可指定返回值规则)
intStream.asLongStream().forEach(System.out::println);
}
7.forEach / forEachOrdered
这两个方法都是用来遍历流中的元素,是一个终结方法。该方法接收一个 IntConsumer 接口函数,会将每一个流元素交给该函数进行处理。
1.forEach:遍历流中的元素
2.mapToLong:forEachOrdered
同forEach
的区别在于并行流处理下,forEachOrdered会保证实际的处理顺序与流中元素的顺序一致,而forEach方法无法保证,默认的串行流处理下,两者无区别,都能保证处理顺序与流中元素顺序一致。
@Test
public void test08() {
IntStream intStream = IntStream.of(2,6,3,5,9,8,1).parallel();
intStream.forEach(x->{
System.out.println("forEach->"+x);
});
// forEachOrdered()同forEach()方法
// 区别:在于并行流处理下,forEachOrdered会保证实际的处理顺序与流中元素的顺序一致
// 而forEach方法无法保证,默认的串行流处理下,两者无区别,都能保证处理顺序与流中元素顺序一致
IntStream intStream1 = IntStream.of(2,6,3,5,9,8,1).parallel();
intStream1.forEachOrdered(x->{
System.out.println("forEachOrdered->"+x);
});
}
输出结果:
forEach->9
forEach->5
forEach->2
forEach->1
forEach->8
forEach->3
forEach->6
forEachOrdered->2
forEachOrdered->6
forEachOrdered->3
forEachOrdered->5
forEachOrdered->9
forEachOrdered->8
forEachOrdered->1
8.distinct
distinct() 方法,
可以用来去除重复数据
。因为 distinct() 方法是一个非终结方法,所以必须调用终止方法。
@Test
public void test09() {
IntStream intStream = IntStream.of(1, 2, 3, 4, 5, 6, 1, 4, 5, 2);
intStream.distinct().forEach(System.out::println);
}
输出结果:
1
2
3
4
5
6
9.sorted
sorted() 方法,可以用来对 Stream 流中的数据进行排序。
Stream流中的sorted()方法,还允许我们自定义Comparator规则进行排序;参考:JDK8新特性(三):集合之 Stream 流式操作 中的sorted()方法
IntStream流中的sorted()方法,就是纯粹对int数值进行排序,所以也没有Comparator自定义比较器排序的必要
@Test
public void test10() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
intStream.sorted().forEach(System.out::println);
}
输出结果:
1
2
4
5
9
35
10.limit
limit()方法,用来对 Stream 流中的数据进行截取,只取用前 n 个,是一个非终结方法。参数是一个 long 型,如果集合当前长度大于参数则进行截取,否则不进行操作。因为 limit() 是一个非终结方法,所以必须调用终止方法
@Test
public void test11() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
// limit()截取,截取IntStream流中的前4个元素
intStream.limit(4).forEach(System.out::println);
}
输出结果:
1
9
4
35
11.skip
如果希望跳过前几个元素,去取后面的元素,则可以使用 skip()方法,获取一个截取之后的新流,它是一个非终结方法。参数是一个 long 型,如果 Stream 流的当前长度大于 n,则跳过前 n 个,否则将会得到一个长度为 0 的空流。因为 limit() 是一个非终结方法,所以必须调用终止方法。
@Test
public void test11() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
// skip()跳过流中前2个元素,获取剩下的元素
intStream.skip(2).forEach(System.out::println);
}
输出结果:
4
35
5
2
备注:
skip() 和 limit() 配合使用,即可实现类似分页的操作了
//一页10条 分页操作
//第一页
skip(0).limit(10)
//第二页
skip(10).limit(10)
//第三页
skip(20).limit(10)
...
12.reduce
reduce方法,用于执行类似于累加的操作,上一次调用处理函数的结果会作为入参下一次调用的入参;
reduce方法,有如下两个不同参数的方法供调用int reduce(int identity, IntBinaryOperator op); OptionalInt reduce(IntBinaryOperator op);
参数说明:
1.int identity:初始值(是否需要设置初始值,视情况而定)
2.IntBinaryOperator op:计算规则
方法说明:
1.方法1有初始值,返回值为int
2.方法2无初始值,有可能为空的情况,所以返回 OptionalInt 类型
@Test
public void test22() {
// IntStream流
IntStream intStream = IntStream.of(1, 1, 1, 1, 1, 1);
// 1.设置初始值为10,(求和则会在10的基础上进行计算,计算结果为16,返回值类型为int)
// 基础写法
int reduce = intStream.reduce(10, new IntBinaryOperator() {
@Override
public int applyAsInt(int left, int right) {
return left + right;
}
});
System.out.println(reduce); // 16
// 简写
IntStream intStream1 = IntStream.of(1, 1, 1, 1, 1, 1);
int reduce1 = intStream1.reduce(10, Integer::sum);
System.out.println(reduce1); // 16
// 2.无初始值(因为返回值可能为空,所以返回类型为OptionInt)
// 因为没有初始值,int类型默认为0,所以计算结果为6
IntStream intStream2 = IntStream.of(1, 1, 1, 1, 1, 1);
OptionalInt reduce2 = intStream2.reduce(Integer::sum);
System.out.println(reduce2.getAsInt()); // 6
}
分析过程:
13.sum / min / max / count / average / summaryStatistics
sum:求和
min:求最小值
max:求最大值
count:计算IntStream流中元素个数
average:求平均值
summaryStatistics:该方法一次调用获取上述5个属性值
@Test
public void test11() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
// sum:求和
int sum = intStream.sum();
System.out.println("sum -> " + sum);
// min:最小值
IntStream intStream1 = IntStream.of(1, 9, 4, 35, 5, 2);
OptionalInt min = intStream1.min();
System.out.println("min -> " + min.getAsInt());
// max:最大值
IntStream intStream2 = IntStream.of(1, 9, 4, 35, 5, 2);
OptionalInt max = intStream2.max();
System.out.println("max -> " + max.getAsInt());
// count:统计流中元素个数
IntStream intStream3 = IntStream.of(1, 9, 4, 35, 5, 2);
long count = intStream3.count();
System.out.println("count -> " + count);
// average:统计流中元素个数
IntStream intStream4 = IntStream.of(1, 9, 4, 35, 5, 2);
OptionalDouble average = intStream4.average();
System.out.println("average -> " + average.getAsDouble());
// summaryStatistics:汇总方法,一次性返回sum/min/max/count/average值
// average:统计流中元素个数
IntStream intStream5 = IntStream.of(1, 9, 4, 35, 5, 2);
IntSummaryStatistics intSummaryStatistics = intStream5.summaryStatistics();
System.out.println("summaryStatistics -> " + intSummaryStatistics.toString());
System.out.println("summaryStatistics.sum -> " + intSummaryStatistics.getSum());
System.out.println("summaryStatistics.min -> " + intSummaryStatistics.getMin());
System.out.println("summaryStatistics.max -> " + intSummaryStatistics.getMax());
System.out.println("summaryStatistics.count -> " + intSummaryStatistics.getCount());
System.out.println("summaryStatistics.average -> " + intSummaryStatistics.getAverage());
}
输出结果:
sum -> 56
min -> 1
max -> 35
count -> 6
average -> 9.333333333333334
summaryStatistics -> IntSummaryStatistics{count=6, sum=56, min=1, average=9.333333, max=35}
summaryStatistics.sum -> 56
summaryStatistics.min -> 1
summaryStatistics.max -> 35
summaryStatistics.count -> 6
summaryStatistics.average -> 9.333333333333334
14.anyMatch / allMatch / noneMatch
这三个方法,均返回
boolean
类型
allMatch:流中的所有元素都满足给定的匹配条件
anyMatch:流中是否存在任何一个元素满足匹配条件
noneMatch:流中的所有元素都不满足给定的匹配条件
@Test
public void test12() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
// allMatch:流中是否所有元素都 > 10
boolean allMatch = intStream.allMatch(val -> val > 10);
System.out.println("allMatch -> " + allMatch);
// anyMatch:流中是否存在一个元素 > 10
IntStream intStream1 = IntStream.of(1, 9, 4, 35, 5, 2);
boolean anyMatch = intStream1.anyMatch(val -> val > 10);
System.out.println("anyMatch -> " + anyMatch);
// noneMatch:流中元素是否都不满足给定条件(流中元素都<10)
IntStream intStream2 = IntStream.of(1, 9, 4, 35, 5, 2);
boolean noneMatch = intStream2.noneMatch(val -> val > 10);
System.out.println("noneMatch -> " + noneMatch);
}
输出结果:
allMatch -> false
anyMatch -> true
noneMatch -> false
15.findFirst / findAny
IntStream流中的这两个方法,均返回 OptionalInt 类型
findFirst:返回IntStream流中的第一个元素,如果流中数据为空,返回空OptionalInt
findAny:返回的元素是不确定的,对于同一个列表多次调用findAny()有可能会返回不同的值。使用findAny()是为了更高效的性能。如果是数据较少,串行地情况下,一般会返回第一个结果,如果是并行的情况,那就不能确保是第一个
@Test
public void test13() {
// findFirst:返回流中的第一个元素
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
OptionalInt first = intStream.findFirst();
System.out.println("findFirst -> " + first.getAsInt());
// findAny:串行地情况下,一般会返回第一个结果.如果是并行的情况,那就不能确保是第一个
IntStream intStream1 = IntStream.of(1, 9, 4, 35, 5, 2).parallel();
OptionalInt any = intStream1.findAny();
System.out.println("findAny -> " + any.getAsInt());
}
输出结果:
findFirst -> 1
findAny -> 35
16.sequential / parallel
sequential:串行(默认为串行,可以不使用sequential()方法)
parallel:并行
/**
* sequential:串行
*/
@Test
public void test14() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
long start = System.currentTimeMillis();
intStream.sequential().forEach(val -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + val);
});
long end = System.currentTimeMillis();
System.out.println("sequential串行,用时:" + (end - start) + "ms");
}
输出结果:
main:1
main:9
main:4
main:35
main:5
main:2
sequential串行,用时:6037ms
分析:
sequential串行:只有main主线程执行,共耗时6037ms
/**
* parallel:并行
*/
@Test
public void test15() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
long start = System.currentTimeMillis();
intStream.parallel().forEach(val -> {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + ":" + val);
});
long end = System.currentTimeMillis();
System.out.println("parallel并行,用时:" + (end - start) + "ms");
}
执行结果:
ForkJoinPool.commonPool-worker-2:2
ForkJoinPool.commonPool-worker-3:1
ForkJoinPool.commonPool-worker-1:9
ForkJoinPool.commonPool-worker-5:4
ForkJoinPool.commonPool-worker-4:5
main:35
parallel并行,用时:1033ms
分析:
parallel并行:共启动6个线程,共耗时1033ms
17.iterator
iterator: 迭代器,遍历返回流中的元素
@Test
public void test16() {
// iterator:迭代器
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
PrimitiveIterator.OfInt iterator = intStream.iterator();
while (iterator.hasNext()) {
Integer next = iterator.next();
System.out.println("iterator迭代数据:" + next);
}
}
输出结果:
iterator迭代数据:1
iterator迭代数据:9
iterator迭代数据:4
iterator迭代数据:35
iterator迭代数据:5
iterator迭代数据:2
18.boxed
boxed:翻译过来是盒子被包装的意思。即:返回由IntStream流中的元素组成的Stream流,每个box 都装着Integer类
在Stream流中,是没有boxed()方法的;
只有在IntStream、DoubleStream、LongStream 这三种类型的流中,才有boxed()方法
源码:
@Override
public final Stream<Integer> boxed() {
return mapToObj(Integer::valueOf);
}
解析:
①IntStream流中存的是 int 类型的 Stream,而Steam<Integer>是一个存了Integer的Stream。
②看源码发现,boxed()的作用就是将int类型的Stream转成了Integer类型的Stream
。
②即:将IntStream转换成Stream<Integer>的过程,该过程也可通过上面介绍到的mapToObj()方法来实现
@Test
public void test17() {
// boxed:返回一个流中元素的包装类的流(即:将IntStream转成Stream<Integer>类型)
// 1.通过mapToObj()方法的方式返回Stream<xxx>类型
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
intStream.mapToObj(Integer::valueOf).collect(Collectors.toList()).forEach(System.out::println);
// 2.通过boxed()方法的方式返回Stream<Integer>类型
IntStream intStream1 = IntStream.of(1, 9, 4, 35, 5, 2);
Stream<Integer> boxed = intStream1.boxed(); // 看这里,通过boxed返回的是Stream<Integer>类型
List<Integer> collect = boxed.collect(Collectors.toList()); // 转换成List<Integer>类型
}
扩展:
@Test
public void test18() {
// IntStream 转 Stream<Integer>
IntStream intStream = IntStream.of(111, 222);
Stream<Integer> boxed = intStream.boxed();
// Stream<Integer> 转 IntStream
Stream<Integer> integerStream = Stream.of(1111, 222);
IntStream intStream1 = integerStream.mapToInt(Integer::valueOf);
}
19.toArray
toArray:将IntStream流中的元素转换成一个数组
@Test
public void test19() {
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
// toArray:将IntStream流中的元素转换成一个数组
int[] intArray = intStream.toArray();
System.out.println(Arrays.toString(intArray));
}
输出结果:
[1, 9, 4, 35, 5, 2]
20.close / onClose
close:用于关闭Stream流,
onClose:该方法用于注册一个回调函数,它返回的是一个新的流,可以连续调用onClose,注册多个回调方法
@Test
public void test21() {
// IntStream流
IntStream intStream = IntStream.of(1, 9, 4, 35, 5, 2);
// 使用onClose()方法注册多个回调函数
IntStream newStream = intStream
.onClose(() -> System.out.println("1"))
.onClose(() -> System.out.println("2"))
.onClose(() -> System.out.println("3"));
// 调用close()方法关闭流时,会一次执行注册的回调函数
newStream.close();
// 关闭流后,就不能再使用该流了(此处会报错:stream has already been operated upon or closed)
int sum = newStream.sum();
}
输出结果:
// 关闭流时的回调函数内容
1
2
3
// 报错信息
java.lang.IllegalStateException: stream has already been operated upon or closed
21.collect
collect:用于将流中最终计算好的数据进行收集,并返回
collect() 方法的使用,也有很多内容学习,此处内容过多,不做一一列举。
在使用collect()方法时,我们会常用到一个Collectors工具类,该工具类为我们提供了很多日常开发中会用到的一些方法
比如说:
1.将结果收集到List集合
2.将结果收集到Set集合
3.将结果收集到Collection集合中
4.将结果进行聚合计算后返回
… … 等很多工具类,挺好用的。
此处不过多介绍。请参考:JDK8辅助学习(四):Stream流 collect() 方法的详细使用介绍
Example:此处来一个简单的案例,将strem流计算返回的结果,收集到List集合中
@Test
public void test23() {
// IntStream流
IntStream intStream = IntStream.of(2, 9, 12, 35, 38, 8, 13, 39, 58, 86, 63);
// 操作
List<Integer> collect = intStream.filter(val -> val > 10) // 过滤掉<10的,返回:12, 35, 38, 13, 39, 58, 86, 63
.map(val -> 2 * val) // 翻倍,返回:24, 70, 76, 26, 78, 116, 172, 126
.skip(2) // 跳过前2个,返回:76, 26, 78, 116, 172, 126
.limit(4) // 截取前4个,返回:76, 26, 78, 116
.boxed() // IntStream 转 Stream<Integer>
.collect(Collectors.toList()); // 将结果收集至List集合
// 输出
collect.forEach(System.out::println);
}
输出结果:
76
26
78
116
Collectors工具类的使用,更多内容请参考:JDK8辅助学习(四):Stream流 collect() 方法的详细使用介绍
博主写作不易,加个关注呗
求关注、求点赞,加个关注不迷路 ヾ(◍°∇°◍)ノ゙
我不能保证所写的内容都正确,但是可以保证不复制、不粘贴。保证每一句话、每一行代码都是亲手敲过的,错误也请指出,望轻喷 Thanks♪(・ω・)ノ