欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  IT编程

JDK1.8新特性——Collector接口和Collectors工具类

程序员文章站 2023-04-04 14:23:30
本文主要学习了在Java1.8中新增的Collector接口和Collectors工具类,以及使用它们在处理集合时的改进和优化。 ......

jdk1.8新特性——collector接口和collectors工具类

摘要:本文主要学习了在java1.8中新增的collector接口和collectors工具类,以及使用它们在处理集合时的改进和优化。

部分内容来自以下博客:

https://www.jianshu.com/p/7eaa0969b424

流式处理

jdk1.8中新增的流式处理提供了一种高效且易于使用的处理数据的方式,它可以对集合执行非常复杂的查找、过滤和映射数据等操作,极大的简化了对于集合的使用。借助流式处理,可以像使用sql语句一样对集合进行操作。

jdk1.8通过内部迭代来实现对流的处理,一个流式处理可以分为三个部分:转换成流、中间操作、终止操作。

转换成流

对于集合,可以使用集合类中的stream()方法或者parallelstream()方法将集合转换成流。

中间操作

中间操作可以对流进行处理并返回处理后的流对象,多个中间操作可以连接起来形成一个流水线,直到执行终止操作结束流的执行。

终止操作

终止操作会对经过中间操作后得到的流进行处理,返回任何不是流的数据。

collector接口

在对流进行的终止操作中,有一个方法是collect,其作用是收集元素并进行处理,最终返回处理后的非流对象。

查看其方法定义如下:

1 <r, a> r collect(collector<? super t, a, r> collector);

可以看到,collect方法要求传入一个collector接口的实例对象,collector可以看做是用来处理流的工具,在collectors里面封装了很多collector工具。

全局变量

collector主要包含五个参数,它的行为也是由这五个参数来定义的,如下所示:

 1 // supplier参数用于生成结果容器,容器类型为a。
 2 supplier<a> supplier();
 3 // accumulator用于归纳元素,泛型t就是元素,它会将流中的元素同结果容器a发生操作。
 4 biconsumer<a, t> accumulator();
 5 // combiner用于合并两个并行执行的结果,将其合并为最终结果a。
 6 binaryoperator<a> combiner();
 7 // finisher用于将之前完整的结果r转为a。
 8 function<a, r> finisher();
 9 // characteristics表示当前collector的特征值,是一个不可变的set。
10 set<characteristics> characteristics();

枚举

characteristics这个特征值是一个枚举:

1 enum characteristics {
2     // 多线程并行。
3     concurrent,
4     // 无序。
5     unordered,
6     // 无需转换结果。
7     identity_finish
8 }

构造方法

collector拥有两个of方法用于生成collector实例,其中一个拥有上面所有五个参数,另一个四个参数,不包括finisher参数。

 1 // 四参方法,用于生成一个collector,t代表流中的元素,r代表最终的结果。因为没有finisher参数,所以需要有identity_finish特征值。
 2 public static<t, r> collector<t, r, r> of(supplier<r> supplier,
 3                                           biconsumer<r, t> accumulator,
 4                                           binaryoperator<r> combiner,
 5                                           characteristics... characteristics) {
 6     objects.requirenonnull(supplier);
 7     objects.requirenonnull(accumulator);
 8     objects.requirenonnull(combiner);
 9     objects.requirenonnull(characteristics);
10     set<characteristics> cs = (characteristics.length == 0)
11                               ? collectors.ch_id
12                               : collections.unmodifiableset(enumset.of(collector.characteristics.identity_finish,
13                                                                        characteristics));
14     return new collectors.collectorimpl<>(supplier, accumulator, combiner, cs);
15 }
16 
17 // 五参方法,用于生成一个collector,t代表流中的元素,a代表中间结果,r代表最终结果,finisher用于将a转换为r。
18 public static<t, a, r> collector<t, a, r> of(supplier<a> supplier,
19                                              biconsumer<a, t> accumulator,
20                                              binaryoperator<a> combiner,
21                                              function<a, r> finisher,
22                                              characteristics... characteristics) {
23     objects.requirenonnull(supplier);
24     objects.requirenonnull(accumulator);
25     objects.requirenonnull(combiner);
26     objects.requirenonnull(finisher);
27     objects.requirenonnull(characteristics);
28     set<characteristics> cs = collectors.ch_noid;
29     if (characteristics.length > 0) {
30         cs = enumset.noneof(characteristics.class);
31         collections.addall(cs, characteristics);
32         cs = collections.unmodifiableset(cs);
33     }
34     return new collectors.collectorimpl<>(supplier, accumulator, combiner, finisher, cs);
35 }

collectors工具类

collectors是一个工具类,是jdk预实现collector的工具类,它内部提供了多种collector。

tocollection方法

将流中的元素全部放置到一个集合中返回,这里使用collection,泛指多种集合。

方法:

1 public static <t, c extends collection<t>> collector<t, ?, c> tocollection(supplier<c> collectionfactory) {
2     return new collectorimpl<>(
3             collectionfactory, collection<t>::add,
4             (r1, r2) -> { r1.addall(r2); return r1; }, 
5             ch_id);
6 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     linkedlist<string> newlist = list.stream().collect(collectors.tocollection(linkedlist::new));
5     system.out.println(newlist);// [123, 521, 100, 228, 838, 250, 345]
6 }

tolist方法

将流中的元素放置到一个list集合中返回,默认为arraylist。

方法:

1 public static <t>
2 collector<t, ?, list<t>> tolist() {
3     return new collectorimpl<>(
4             (supplier<list<t>>) arraylist::new, list::add,
5             (left, right) -> { left.addall(right); return left; },
6             ch_id);
7 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     list<string> newlist = list.stream().collect(collectors.tolist());
5     system.out.println(newlist);// [123, 521, 100, 228, 838, 250, 345]
6 }

toset方法

将流中的元素放置到一个set集合中返回,默认为hashset。

方法:

1 public static <t> collector<t, ?, set<t>> toset() {
2     return new collectorimpl<>(
3             (supplier<set<t>>) hashset::new, set::add,
4             (left, right) -> { left.addall(right); return left; },
5             ch_unordered_id);
6 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     set<string> newset = list.stream().collect(collectors.toset());
5     system.out.println(newset);// [100, 123, 521, 345, 228, 838, 250]
6 }

tomap方法

根据传入的键生成器和值生成器,将生成的键和值保存到一个map中返回,键和值的生成都依赖于元素,可以指定出现重复键时的处理方案和保存结果的map。

还有支持并发toconcurrentmap方法,同样有三种重载方法,与tomap基本一致,只是它最后使用的map是并发concurrenthashmap。

方法:

 1 // 指定键和值的生成方式,遇到键冲突的情况默认抛出异常,默认使用hashmap。
 2 public static <t, k, u> collector<t, ?, map<k,u>> tomap(
 3             function<? super t, ? extends k> keymapper,
 4             function<? super t, ? extends u> valuemapper) {
 5     return tomap(keymapper, valuemapper, throwingmerger(), hashmap::new);
 6 }
 7 // 指定键和值的生成方式,遇到键冲突的情况使用传入的方法处理,默认使用hashmap。
 8 public static <t, k, u> collector<t, ?, map<k,u>> tomap(
 9             function<? super t, ? extends k> keymapper,
10             function<? super t, ? extends u> valuemapper,
11             binaryoperator<u> mergefunction) {
12     return tomap(keymapper, valuemapper, mergefunction, hashmap::new);
13 }
14 // 指定键和值的生成方式,遇到键冲突的情况使用传入的方法处理,使用传入的map类型返回数据。前两种方式最终还是调用此方法来返回map数据。
15 public static <t, k, u, m extends map<k, u>> collector<t, ?, m> tomap(
16             function<? super t, ? extends k> keymapper,
17             function<? super t, ? extends u> valuemapper,
18             binaryoperator<u> mergefunction,
19             supplier<m> mapsupplier) {
20     biconsumer<m, t> accumulator = (map, element) -> map.merge(
21             keymapper.apply(element), 
22             valuemapper.apply(element), 
23             mergefunction);
24     return new collectorimpl<>(mapsupplier, accumulator, mapmerger(mergefunction), ch_id);
25 }

实例:

 1 public static void main(string[] args) {
 2     map<string, string> newmap = null;
 3     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 4     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 5     // 123和100的键都是1,导致冲突,默认抛出异常,使用limit截取前两个元素。
 6     newmap = list.stream().limit(2).collect(collectors.tomap(e -> e.substring(0, 1), e -> e));
 7     system.out.println(newmap);// {1=123, 5=521}
 8     // 传入主键冲突时的处理方法,保留先插入的值,默认使用hashmap,对主键由小到大排序。
 9     newmap = list.stream().collect(collectors.tomap(e -> e.substring(0, 1), e -> e, (m, n) -> m));
10     system.out.println(newmap);// {1=123, 2=228, 3=345, 5=521, 8=838}
11     // 传入主键冲突时的处理方法,保留新插入的值,默认使用linkedhashmap,对主键按照插入顺序排序。
12     newmap = list.stream().collect(collectors.tomap(e -> e.substring(0, 1), e -> e, (m, n) -> n, linkedhashmap::new));
13     system.out.println(newmap);// {1=100, 5=521, 2=250, 8=838, 3=345}
14 }

joining方法

将流中的元素全部以字符串的方式连接到一起,可以指定连接符,也可以指定前后缀。

方法:

 1 // 将流中的元素全部以字符串的方式连接到一起,不使用连接符,也不指定前后缀。
 2 public static collector<charsequence, ?, string> joining() {
 3     return new collectorimpl<charsequence, stringbuilder, string>(
 4             stringbuilder::new, stringbuilder::append,
 5             (r1, r2) -> { r1.append(r2); return r1; },
 6             stringbuilder::tostring, ch_noid);
 7 }
 8 // 将流中的元素全部以字符串的方式连接到一起,使用指定的连接符,不指定前后缀。
 9 public static collector<charsequence, ?, string> joining(charsequence delimiter) {
10     return joining(delimiter, "", "");
11 }
12 // 将流中的元素全部以字符串的方式连接到一起,使用指定的连接符,使用指定的前后缀。
13 public static collector<charsequence, ?, string> joining(charsequence delimiter,
14                                                          charsequence prefix,
15                                                          charsequence suffix) {
16     return new collectorimpl<>(
17             () -> new stringjoiner(delimiter, prefix, suffix),
18             stringjoiner::add, stringjoiner::merge,
19             stringjoiner::tostring, ch_noid);
20 }

实例:

 1 public static void main(string[] args) {
 2     string str = null;
 3     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 4     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 5     str = list.stream().collect(collectors.joining());
 6     system.out.println(str);// 123521100228838250345
 7     str = list.stream().collect(collectors.joining("-"));
 8     system.out.println(str);// 123-521-100-228-838-250-345
 9     str = list.stream().collect(collectors.joining("-", "<", ">"));
10     system.out.println(str);// <123-521-100-228-838-250-345>
11 }

mapping方法

将流中的元素按照传入的方法进行处理,并将结果按照指定的格式返回。

方法:

 1 public static <t, u, a, r>
 2 collector<t, ?, r> mapping(
 3             function<? super t, ? extends u> mapper,
 4             collector<? super u, a, r> downstream) {
 5     biconsumer<a, ? super u> downstreamaccumulator = downstream.accumulator();
 6     return new collectorimpl<>(
 7             downstream.supplier(),
 8             (r, t) -> downstreamaccumulator.accept(r, mapper.apply(t)),
 9             downstream.combiner(),
10             downstream.finisher(),
11             downstream.characteristics());
12 }

实例:

1 public static void main(string[] args) {
2     list<score> scorelist = new arraylist<score>();
3     scorelist.add(new score("2019", "10", "张三", 1));
4     scorelist.add(new score("2019", "11", "李四", 1));
5     scorelist.add(new score("2019", "12", "王五", 1));
6     list<string> names = scorelist.stream().collect(collectors.mapping(score::getname, collectors.tolist()));
7     system.out.println(names);// [张三, 李四, 王五]
8 }

collectingandthen方法

该方法是按照传入的collector处理完之后,对归纳的结果进行再处理。

方法:

 1 public static<t,a,r,rr> collector<t,a,rr> collectingandthen(
 2             collector<t,a,r> downstream,
 3             function<r,rr> finisher) {
 4     set<collector.characteristics> characteristics = downstream.characteristics();
 5     if (characteristics.contains(collector.characteristics.identity_finish)) {
 6         if (characteristics.size() == 1)
 7             characteristics = collectors.ch_noid;
 8         else {
 9             characteristics = enumset.copyof(characteristics);
10             characteristics.remove(collector.characteristics.identity_finish);
11             characteristics = collections.unmodifiableset(characteristics);
12         }
13     }
14     return new collectorimpl<>(downstream.supplier(),
15                                downstream.accumulator(),
16                                downstream.combiner(),
17                                downstream.finisher().andthen(finisher),
18                                characteristics);
19 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     integer size = list.stream().collect(collectors.collectingandthen(collectors.tolist(), list::size));
5     system.out.println(size);// 7
6 }

counting方法

该方法主要用来计数。

方法:

1 public static <t> collector<t, ?, long> counting() {
2     return reducing(0l, e -> 1l, long::sum);
3 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     long count = list.stream().collect(collectors.counting());
5     system.out.println(count);// 7
6 }

reducing方法

对流中的元素做统计归纳,有三个重载方法,和stream里的三个reduce方法对应,二者是可以替换使用的,作用完全一致。

方法:

 1 // 返回一个可以直接产生optional类型结果的collector,没有初始值。
 2 public static <t> collector<t, ?, optional<t>> reducing(binaryoperator<t> op) {
 3     class optionalbox implements consumer<t> {
 4         t value = null;
 5         boolean present = false;
 6 
 7         @override
 8         public void accept(t t) {
 9             if (present) {
10                 value = op.apply(value, t);
11             }
12             else {
13                 value = t;
14                 present = true;
15             }
16         }
17     }
18     return new collectorimpl<t, optionalbox, optional<t>>(
19             optionalbox::new, optionalbox::accept,
20             (a, b) -> { if (b.present) a.accept(b.value); return a; },
21             a -> optional.ofnullable(a.value), ch_noid);
22 }
23 // 返回一个可以直接产生结果的collector,指定初始值。
24 public static <t> collector<t, ?, t> reducing(t identity, binaryoperator<t> op) {
25     return new collectorimpl<>(
26             boxsupplier(identity),
27             (a, t) -> { a[0] = op.apply(a[0], t); },
28             (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
29             a -> a[0],
30             ch_noid);
31 }
32 // 返回一个可以直接产生结果的collector,指定初始值,在返回结果之前先使用传入的方法将流进行转换。
33 public static <t, u> collector<t, ?, u> reducing(
34             u identity,
35             function<? super t, ? extends u> mapper,
36             binaryoperator<u> op) {
37     return new collectorimpl<>(
38             boxsupplier(identity),
39             (a, t) -> { a[0] = op.apply(a[0], mapper.apply(t)); },
40             (a, b) -> { a[0] = op.apply(a[0], b[0]); return a; },
41             a -> a[0], ch_noid);
42 }

实例:

 1 public static void main(string[] args) {
 2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 4     optional<integer> optional = list.stream().limit(4).map(string::length).collect(collectors.reducing(integer::sum));
 5     system.out.println(optional);// optional[12]
 6     integer integer = list.stream().limit(3).map(string::length).collect(collectors.reducing(0, integer::sum));
 7     system.out.println(integer);// 9
 8     integer sum = list.stream().limit(4).collect(collectors.reducing(0, string::length, integer::sum));
 9     system.out.println(sum);// 12
10 }

minby方法和maxby方法

生成一个用于获取最小值或者最大值的optional结果的collector。

方法:

1 public static <t> collector<t, ?, optional<t>> minby(comparator<? super t> comparator) {
2     return reducing(binaryoperator.minby(comparator));
3 }
4 public static <t> collector<t, ?, optional<t>> maxby(comparator<? super t> comparator) {
5     return reducing(binaryoperator.maxby(comparator));
6 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     optional<string> max = list.stream().collect(collectors.maxby((m, n) -> integer.valueof(m) - integer.valueof(n)));
5     system.out.println(max);// optional[838]
6     optional<string> min = list.stream().collect(collectors.minby((m, n) -> integer.valueof(m) - integer.valueof(n)));
7     system.out.println(min);// optional[100]
8 }

summingint方法、summinglong方法和summingdouble方法

生成一个用于求元素和的collector,首先将元素转换类型,然后再求和。

参数的作用就是将元素转换为指定的类型,最后结果与转换后类型一致。

方法:

 1 public static <t> collector<t, ?, integer> summingint(tointfunction<? super t> mapper) {
 2     return new collectorimpl<>(
 3             () -> new int[1],
 4             (a, t) -> { a[0] += mapper.applyasint(t); },
 5             (a, b) -> { a[0] += b[0]; return a; },
 6             a -> a[0], ch_noid);
 7 }
 8 public static <t> collector<t, ?, long> summinglong(tolongfunction<? super t> mapper) {
 9     return new collectorimpl<>(
10             () -> new long[1],
11             (a, t) -> { a[0] += mapper.applyaslong(t); },
12             (a, b) -> { a[0] += b[0]; return a; },
13             a -> a[0], ch_noid);
14 }
15 public static <t> collector<t, ?, double> summingdouble(todoublefunction<? super t> mapper) {
16     return new collectorimpl<>(
17             () -> new double[3],
18             (a, t) -> { sumwithcompensation(a, mapper.applyasdouble(t));
19                         a[2] += mapper.applyasdouble(t); },
20             (a, b) -> { sumwithcompensation(a, b[0]);
21                         a[2] += b[2]; return sumwithcompensation(a, b[1]); },
22             a -> computefinalsum(a), ch_noid);
23 }

实例:

 1 public static void main(string[] args) {
 2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 4     integer intcollect = list.stream().collect(collectors.summingint(integer::parseint));
 5     system.out.println(intcollect);// 2405
 6     long longcollect = list.stream().collect(collectors.summinglong(long::parselong));
 7     system.out.println(longcollect);// 2405
 8     double doublecollect = list.stream().collect(collectors.summingdouble(double::parsedouble));
 9     system.out.println(doublecollect);// 2405.0
10 }

summarizingint方法、summarizinglong方法和summarizingdouble方法

这三个方法适用于汇总的,返回值分别是intsummarystatistics、longsummarystatistics和doublesummarystatistics。

在这些返回值中包含有流中元素的指定结果的数量、和、最大值、最小值、平均值。

方法:

 1 public static <t> collector<t, ?, intsummarystatistics> summarizingint(tointfunction<? super t> mapper) {
 2     return new collectorimpl<t, intsummarystatistics, intsummarystatistics>(
 3             intsummarystatistics::new,
 4             (r, t) -> r.accept(mapper.applyasint(t)),
 5             (l, r) -> { l.combine(r); return l; }, ch_id);
 6 }
 7 public static <t> collector<t, ?, longsummarystatistics> summarizinglong(tolongfunction<? super t> mapper) {
 8     return new collectorimpl<t, longsummarystatistics, longsummarystatistics>(
 9             longsummarystatistics::new,
10             (r, t) -> r.accept(mapper.applyaslong(t)),
11             (l, r) -> { l.combine(r); return l; }, ch_id);
12 }
13 public static <t> collector<t, ?, doublesummarystatistics> summarizingdouble(todoublefunction<? super t> mapper) {
14     return new collectorimpl<t, doublesummarystatistics, doublesummarystatistics>(
15             doublesummarystatistics::new,
16             (r, t) -> r.accept(mapper.applyasdouble(t)),
17             (l, r) -> { l.combine(r); return l; }, ch_id);
18 }

实例:

 1 public static void main(string[] args) {
 2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 4     intsummarystatistics intsummarystatistics = list.stream().collect(collectors.summarizingint(integer::parseint));
 5     system.out.println(intsummarystatistics);// {count=7, sum=2405, min=100, average=343.571429, max=838}
 6     longsummarystatistics longsummarystatistics = list.stream().collect(collectors.summarizinglong(long::parselong));
 7     system.out.println(longsummarystatistics);// {count=7, sum=2405, min=100, average=343.571429, max=838}
 8     doublesummarystatistics doublesummarystatistics = list.stream().collect(collectors.summarizingdouble(double::parsedouble));
 9     system.out.println(doublesummarystatistics);// {count=7, sum=2405.000000, min=100.000000, average=343.571429, max=838.000000}
10 }

averagingint方法、averaginglong方法和averagingdouble方法

生成一个用于求元素平均值的collector,首先将元素转换类型,然后再求平均值。

参数的作用就是将元素转换为指定的类型,求平均值涉及到除法操作,结果一律为double类型。

方法:

 1 public static <t> collector<t, ?, double> averagingint(tointfunction<? super t> mapper) {
 2     return new collectorimpl<>(
 3             () -> new long[2],
 4             (a, t) -> { a[0] += mapper.applyasint(t); a[1]++; },
 5             (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
 6             a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], ch_noid);
 7 }
 8 public static <t> collector<t, ?, double> averaginglong(tolongfunction<? super t> mapper) {
 9     return new collectorimpl<>(
10             () -> new long[2],
11             (a, t) -> { a[0] += mapper.applyaslong(t); a[1]++; },
12             (a, b) -> { a[0] += b[0]; a[1] += b[1]; return a; },
13             a -> (a[1] == 0) ? 0.0d : (double) a[0] / a[1], ch_noid);
14 }
15 public static <t> collector<t, ?, double> averagingdouble(todoublefunction<? super t> mapper) {
16     return new collectorimpl<>(
17             () -> new double[4],
18             (a, t) -> { sumwithcompensation(a, mapper.applyasdouble(t)); a[2]++; a[3]+= mapper.applyasdouble(t); },
19             (a, b) -> { sumwithcompensation(a, b[0]); sumwithcompensation(a, b[1]); a[2] += b[2]; a[3] += b[3]; return a; },
20             a -> (a[2] == 0) ? 0.0d : (computefinalsum(a) / a[2]), ch_noid);
21 }

实例:

 1 public static void main(string[] args) {
 2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 4     double intaverage = list.stream().collect(collectors.averagingint(integer::parseint));
 5     system.out.println(intaverage);// 343.57142857142856
 6     double longaverage = list.stream().collect(collectors.averaginglong(long::parselong));
 7     system.out.println(longaverage);// 343.57142857142856
 8     double doubleaverage = list.stream().collect(collectors.averagingdouble(double::parsedouble));
 9     system.out.println(doubleaverage);// 343.57142857142856
10 }

groupingby方法

生成一个拥有分组功能的collector,有三个重载方法。

方法:

 1 // 只需一个分组参数classifier,内部自动将结果保存到一个map中,每个map键的类型即classifier的结果类型,默认将组的元素保存在list中。
 2 public static <t, k> collector<t, ?, map<k, list<t>>> groupingby(
 3             function<? super t, ? extends k> classifier) {
 4     return groupingby(classifier, tolist());
 5 }
 6 // 在上面方法的基础上增加了对流中元素的处理方式的collector,默认是list。
 7 public static <t, k, a, d> collector<t, ?, map<k, d>> groupingby(
 8             function<? super t, ? extends k> classifier,
 9             collector<? super t, a, d> downstream) {
10     return groupingby(classifier, hashmap::new, downstream);
11 }
12 // 在第二个方法的基础上再添加了结果map的生成方法,默认是hashmap。
13 public static <t, k, d, a, m extends map<k, d>> collector<t, ?, m> groupingby(
14             function<? super t, ? extends k> classifier,
15             supplier<m> mapfactory,
16             collector<? super t, a, d> downstream) {
17     supplier<a> downstreamsupplier = downstream.supplier();
18     biconsumer<a, ? super t> downstreamaccumulator = downstream.accumulator();
19     biconsumer<map<k, a>, t> accumulator = (m, t) -> {
20         k key = objects.requirenonnull(classifier.apply(t), "element cannot be mapped to a null key");
21         a container = m.computeifabsent(key, k -> downstreamsupplier.get());
22         downstreamaccumulator.accept(container, t);
23     };
24     binaryoperator<map<k, a>> merger = collectors.<k, a, map<k, a>>mapmerger(downstream.combiner());
25     @suppresswarnings("unchecked")
26     supplier<map<k, a>> mangledfactory = (supplier<map<k, a>>) mapfactory;
27 
28     if (downstream.characteristics().contains(collector.characteristics.identity_finish)) {
29         return new collectorimpl<>(mangledfactory, accumulator, merger, ch_id);
30     }
31     else {
32         @suppresswarnings("unchecked")
33         function<a, a> downstreamfinisher = (function<a, a>) downstream.finisher();
34         function<map<k, a>, m> finisher = intermediate -> {
35             intermediate.replaceall((k, v) -> downstreamfinisher.apply(v));
36             @suppresswarnings("unchecked")
37             m castresult = (m) intermediate;
38             return castresult;
39         };
40         return new collectorimpl<>(mangledfactory, accumulator, merger, finisher, ch_noid);
41     }
42 }

实例:

 1 public static void main(string[] args) {
 2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
 3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
 4     map<string, list<string>> groupbyfirst = list.stream().collect(collectors.groupingby(e -> e.substring(0, 1)));
 5     system.out.println(groupbyfirst);// {1=[123, 100], 2=[228, 250], 3=[345], 5=[521], 8=[838]}
 6     map<string, set<string>> groupbylast = list.stream().collect(collectors.groupingby(e -> e.substring(e.length() - 1), collectors.toset()));
 7     system.out.println(groupbylast);// {0=[100, 250], 1=[521], 3=[123], 5=[345], 8=[228, 838]}
 8     map<integer, set<string>> groupbylength = list.stream().collect(collectors.groupingby(string::length, hashmap::new, collectors.toset()));
 9     system.out.println(groupbylength);// {3=[100, 123, 521, 345, 228, 838, 250]}
10 }

partitioningby方法

将流中的元素按照给定的校验规则的结果分为两个部分,放到map中返回,键是boolean类型,值为元素的列表list。

方法:

 1 // 只需一个校验参数predicate。
 2 public static <t> collector<t, ?, map<boolean, list<t>>> partitioningby(predicate<? super t> predicate) {
 3     return partitioningby(predicate, tolist());
 4 }
 5 // 在上面方法的基础上增加了对流中元素的处理方式的collector,默认的处理方法就是collectors.tolist()。
 6 public static <t, d, a> collector<t, ?, map<boolean, d>> partitioningby(predicate<? super t> predicate,
 7                                                 collector<? super t, a, d> downstream) {
 8     biconsumer<a, ? super t> downstreamaccumulator = downstream.accumulator();
 9     biconsumer<partition<a>, t> accumulator = (result, t) ->
10             downstreamaccumulator.accept(predicate.test(t) ? result.fortrue : result.forfalse, t);
11     binaryoperator<a> op = downstream.combiner();
12     binaryoperator<partition<a>> merger = (left, right) ->
13             new partition<>(op.apply(left.fortrue, right.fortrue),
14                             op.apply(left.forfalse, right.forfalse));
15     supplier<partition<a>> supplier = () ->
16             new partition<>(downstream.supplier().get(),
17                             downstream.supplier().get());
18     if (downstream.characteristics().contains(collector.characteristics.identity_finish)) {
19         return new collectorimpl<>(supplier, accumulator, merger, ch_id);
20     }
21     else {
22         function<partition<a>, map<boolean, d>> finisher = par ->
23                 new partition<>(downstream.finisher().apply(par.fortrue),
24                                 downstream.finisher().apply(par.forfalse));
25         return new collectorimpl<>(supplier, accumulator, merger, finisher, ch_noid);
26     }
27 }

实例:

1 public static void main(string[] args) {
2     list<string> list = arrays.aslist("123", "521", "100", "228", "838", "250", "345");
3     system.out.println(list);// [123, 521, 100, 228, 838, 250, 345]
4     map<boolean, list<string>> morethan = list.stream().collect(collectors.partitioningby(e -> integer.parseint(e) > 300));
5     system.out.println(morethan);// {false=[123, 100, 228, 250], true=[521, 838, 345]}
6     map<boolean, set<string>> lessthan = list.stream().collect(collectors.partitioningby(e -> integer.parseint(e) < 300, collectors.toset()));
7     system.out.println(lessthan);// {false=[521, 345, 838], true=[100, 123, 228, 250]}
8 }