jdk1.8的stream学习之四

今天来学习最后一个操作方法collect
日常流式操作后,需要对结果处理,则可以用这个方法来实现。

collect(Collector<? super P_OUT, A, R> collector)

这里我们首先要学一下Collectors这个类,这个类里有个静态内部类是Collector的实现类,也就是说,Collectors类里的静态方法内部实现都是基于Collector的实现类

Collectors.toCollection(Supplier<C> collectionFactory)

这个方法将流收集为一个实现了collection接口的容器类.如下所示,将一个流转化为一个hashSet.只要是collection接口的实现类,都可以在这里轻松转换。

HashSet<Integer> collect =Stream.of(2,3,6,8).collect(Collectors.toCollection(HashSet::new));

toList()

这个不多说,就是直接将流转化为一个Arraylist对象

toSet()

这个也不多说,转化为一个hashSet对象

joining()

这个不多说,将流中的元素拼接成字符串。流中的元素首先必须先转换为string类型。字符串的拼接是通过StringBuilder::append完成的。

    String collect = Stream.of("hello", " ", "world").collect(Collectors.joining());
    输出:hello world

joining(分隔符)

这个可以指定分割符号来进行字符串拼接。下面的代码结果同上

    String collect = Stream.of("hello", "world").collect(Collectors.joining("  "));
    输出:hello world

joining(分隔符,前缀,后缀)

这里方法里面可以指定分隔符,然后可以指定字符串的前缀,后缀

    String collect = Stream.of("hello", "world").collect(Collectors.joining(",","{","}"));
    输出:{hello,world}

mapping(Function<? super T, ? extends U> mapper,Collector<? super U, A, R> downstream) 函数

这个函数从源码的功能来看,mapping函数接收2个参数,第一个参数就是一个运算式,第二个参数是接受第一个参数运算后的结果,可以继续用Collector去处理。明白了这个数据的流向,那么我们来看看怎么用
比如:有一个字符串数组,想把字符串数组先转成大写,然后在拼接。可以有2种实现方式。下面的上下两种方式效果是一样的。

    String collect = Stream.of("a","b","c").map(s->s.toUpperCase()).collect(Collectors.joining());
    String collect1 = Stream.of("a","b","c").collect(Collectors.mapping(s -> s.toUpperCase(), Collectors.joining()));
    System.out.println(collect);
    System.out.println(collect1);

collectingAndThen(Collector<T,A,R> downstream,Function<R,RR> finisher)

见名知意,这个操作先把结果可以用自身函数处理一遍,然后可以继续用第二个函数把之前一补处理完的函数继续用新函数再次进行运算
比如如下图,将一个流处理完成后,想变成一个不可再次一被操作的集合,可以通过下列方式去完成。就是第一个参数处理的结果,作为第二个行为参数的入参,且一定是一个接受一个入参,然后进过运算有返回值的一个行为函数,最终结果是以第二个行为函数操作的结果。

    Collection<String> collect = Stream.of("a", "b", "c").collect(Collectors.collectingAndThen(Collectors.toList(), a -> Collections.unmodifiableCollection(a)));
    System.out.println(collect);
    输出结果是一个不支持修改的集合。

counting 函数,是一个统计函数,返回流中元素的个数。

    Long collect = Stream.of("a", "b", "c").collect(Collectors.counting());
    System.out.println(collect);
    输出结果是3,代表流中元素个数是3个

minBy maxBy 分别返回流中按照传入的比较规则返回最大最小值。

    Optional<Person> collect = Stream.of(new Person("a", 11), new Person("b", 12), new Person("c", 22)).collect(Collectors.minBy((a, b) -> a.getAge() - b.getAge()));
    Optional<Person> collect1 = Stream.of(new Person("a", 11), new Person("b", 12), new Person("c", 22)).collect(Collectors.minBy((a, b) -> b.getAge() - a.getAge()));
    System.out.println(JSONObject.toJSONString(collect.get()));
    System.out.println(JSONObject.toJSONString(collect1.get()));
    操作返回结果是:
    {"age":11,"name":"a"}
    {"age":22,"name":"c"}

summingInt() summingLong() summingDouble()

需要传入一个基本类型的数字,然后这个函数会对传入的数字进行求和。
如下所示,有3个Person对象,想知道这三个对象的年龄和是多少,则可以通过这个函数来进行运算。运算过程如下,流中的每一个元素会传入到函数中,然后传入的对象需要转换成对于的基本类型,函数会将基本类型进行求和。

    Integer collect = Stream.of(new Person("a", 11), new Person("b", 12), new Person("c", 22)).
            collect(Collectors.summingInt(value -> value.getAge()));
    System.out.println(collect);
    操作返回结果是:
    45

averagingInt() averagingLong() averagingDouble()

需要传入对应的基本类型,然后函数内部会对传入的数字进行求平均. 原理同上,需要将传入的对象转换为对应的基本类型,最后进行求平均

reducing()

这个函数和reduce函数的用法是一样的。这里再次用3个demo来说明下

    一个参数:
    Optional<Person> collect = Stream.of(new Person("张三", 13), new Person("李四", 13)).
            collect(Collectors.reducing(BinaryOperator.minBy(Comparator.comparing(Person::getAge))));
    System.out.println(collect.get());
    2个参数:
    Integer collect = Stream.of(1,2,3,4,5).
            collect(Collectors.reducing(0,(a,b) -> a+b));
    System.out.println(collect);
    3个参数:
         ArrayList<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5);
    Integer collect = integers.parallelStream().
            collect(Collectors.reducing(0, e -> (Integer) e, (c, d) -> c + d));
    System.out.println(collect);

groupingBy 分组函数

分组函数的目标很简单,就是基于一定的规则进行分组。如下所示,对流中的数据进行奇数和偶数分组。

    ArrayList<Integer> integers = Lists.newArrayList(1, 2, 3, 4, 5,6);
    Map<Integer, List<Integer>> collect = integers.stream().
            collect(Collectors.groupingBy(a -> (a)%2));
    System.out.println(collect);
    输出结果如下:{0=[2, 4, 6], 1=[1, 3, 5]}

groupingByConcurrent 很简单,就是分组后返回一个concurrentMap

这个用法和普通的groupingby是一样的用法,传入一个分组的标准。比如按人的年龄分组。如下:

    ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",11),new Person("b",14));
    ConcurrentMap<Integer, List<Person>> collect = persons.stream().
            collect(Collectors.groupingByConcurrent(a -> a.getAge()));
    System.out.println(JSONObject.toJSONString(collect));
    输出如下:
    {11:[{"age":11,"name":"a"},{"age":11,"name":"c"}],12:[{"age":12,"name":"b"}],14:[{"age":14,"name":"b"}]}

partitioningBy 和groupingby返回的不一样的地方在于,返回的是一个key为布尔类型的key,也就是只能返回true,false两个key。

比如有几个人,判断是否是成年人。

    ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",18),new Person("b",19));
    Map<Boolean, List<Person>> collect = persons.stream().
            collect(Collectors.partitioningBy(a -> a.getAge() > 17));
    System.out.println(JSONObject.toJSONString(collect));
    输出结果如下:
    {false:[{"age":11,"name":"a"},{"age":12,"name":"b"}],true:[{"age":18,"name":"c"},{"age":19,"name":"b"}]}

toMap 这个可以将流转换成map.

比如同样还是上面4个人,想用年龄做key,名字做value。成功的将一个对象的list转换成某2个属性的map集合

    ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",18),new Person("b",19));
    Map<Integer, String> collect = persons.stream().
            collect(Collectors.toMap(a -> a.getAge(), b -> b.getName()));
    System.out.println(JSONObject.toJSONString(collect));
    输出如下:
    {18:"c",19:"b",11:"a",12:"b"}

toConcurrentMap 这个和上面一样,只是返回的是ConcurrentMap

summarizingInt 统计类型类操作。可以将流中的元素转换成int类型。返回一个IntSummaryStatistics对象。这个对象可以做统计,求平均数,最大,最小,和等操作。

比如想求上面列表中人的年龄之和。平均数,最大年龄,最小年龄

    ArrayList<Person> persons = Lists.newArrayList(new Person("a",11),new Person("b",12),new Person("c",18),new Person("b",19));
    IntSummaryStatistics collect = persons.stream().
            collect(Collectors.summarizingInt(a -> a.getAge()));
    System.out.println(collect.getAverage());
    System.out.println(collect.getCount());
    System.out.println(collect.getMax());
    System.out.println(collect.getMin());
    System.out.println(collect.getSum());

这里流操作基本就学完了。

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,290评论 4 363
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,399评论 1 294
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 109,021评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,034评论 0 207
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,412评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,651评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,902评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,605评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,339评论 1 246
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,586评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,076评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,400评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,060评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,851评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,685评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,595评论 2 270

推荐阅读更多精彩内容

  • Java 8函数式编程学习笔记 author:Gavin date:2018/11/09 什么是函数式编程 在思考...
    安静点就睡吧阅读 1,225评论 0 10
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,517评论 0 38
  • “#本文参加‘青春大赛’,本人保证本文为本人原创,如有问题则与主办方无关,自愿放弃评优评奖资格”。 作 者:严...
    凉yaasic阅读 457评论 2 22
  • 文/向上 山崩地裂 震动了整个大地 晃动的山脉 憾动的河流 惊动了多少人心 牵动了多少情怀 原本美丽可爱的大地 你...
    A向上阅读 757评论 20 32
  • 俏叶繁花迷欲眼,风轻香暖入心田。 此生惟愿春光驻,常向枝头对笑妍。
    诗徒儿阅读 629评论 4 12