JDK8-Stream-Collectors

Collectors类作为Collector接口对应的工具类,除提供了对应的实现类(CollectorImpl)以外,还提供了各种快速生成Collector实例的工具方法.

JDK8-Stream

toList/toSet/(toCollection)

无入参, 转set集合、List集合或自定义的集合

@Test
public void test1() {
    // 转Set集合
    Set<String> set = Stream.of("ZH", "cn", "hello", "Word").collect(Collectors.toSet());
    // 转List集合
    List<String> list = Stream.of("ZH", "cn", "hello", "Word").collect(Collectors.toList());
    // 特定转换
    LinkedList linkedList = Stream.of("ZH", "cn", "hello", "Word").collect(Collectors.toCollection(()->{
        return new LinkedList<>();
    }));
}

toMap/toConcurrentMap及各种重载形式

此两类方法之间为是否并发的区别,最终结果分别为Map和ConcurrentMap,同时各自有三种重载形式

入参说明

keyMapper: 将stream内部元素映射为key的表达式
valueMapper: 将stream内部元素映射为value的表达式
mergeFunction: 当同一个key对应的value冲突时,重新映射的表达式
mapSupplier: map的supplier

// 只需要提供key的生成器和value生成器
public static <T, K, U>
Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper) {
    return toMap(keyMapper, valueMapper, throwingMerger(), HashMap::new);
}
// 只需要提供key的生成器、value生成器、同一个key对应的value冲突时,重新映射的表达式
public static <T, K, U>
    Collector<T, ?, Map<K,U>> toMap(Function<? super T, ? extends K> keyMapper,
                                    Function<? super T, ? extends U> valueMapper,
                                    BinaryOperator<U> mergeFunction) {
        return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
    }
// 只需要提供key的生成器、value生成器、同一个key对应的value冲突时,重新映射的表达式、map的生成方法
public static <T, K, U, M extends Map<K, U>>
    Collector<T, ?, M> toMap(Function<? super T, ? extends K> keyMapper,
                                Function<? super T, ? extends U> valueMapper,
                                BinaryOperator<U> mergeFunction,
                                Supplier<M> mapSupplier) {
        BiConsumer<M, T> accumulator
                = (map, element) -> map.merge(keyMapper.apply(element),
                                              valueMapper.apply(element), mergeFunction);
        return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
    }

示例:

/**
 * toMap/toConcurrentMap及各种重载形式
 */
@Test
public void testToMap() {
    List<Person> listPerson = new ArrayList<>();
    listPerson.add(new Person(10, "张三"));
    listPerson.add(new Person(12, "李四"));
    listPerson.add(new Person(14, "王五"));
    // 简单API的使用
    Map result = listPerson.stream().collect(Collectors.toMap(
            // key的生成
            (item) -> {
                return item.getId();
            },
            // value的生成
            (item) -> {
                return item;
            }));

    System.out.println(result);//{10=Person(id=10, name=张三), 12=Person(id=12, name=李四), 14=Person(id=14, name=王五)}

    listPerson.add(new Person(14, "王麻子"));
    // 复杂API的使用
    result = listPerson.stream().collect(Collectors.toMap(
            // 将stream内部元素映射为key的表达式
            (item) -> item.getId(),
            // 将stream内部元素映射为value的表达式
            (item) -> item,
            // 同一个key对应的value冲突时,重新映射的表达式
            (item1Value, item2Value) -> {
                if (item1Value.getName().length() > item2Value.getName().length()) {
                    return item1Value;
                } else {
                    return item2Value;
                }
            },
            // map的构造器
            () -> {
                return new TreeMap();
            }));
    System.out.println(result);//{10=Person(id=10, name=张三), 12=Person(id=12, name=李四), 14=Person(id=14, name=王麻子)}

}

joining 连接器

将steam里的元素连接成一个String

@Test
public void testJoining() {
    String result = Stream.of("ZH", "cn", "hello", "Word").collect(Collectors.joining());
    System.out.println(result);//ZHcnhelloWord
    // 连接符、前缀、后缀
    result = Stream.of("ZH", "cn", "hello", "Word").collect(Collectors.joining("-", "pre", "fix"));
    System.out.println(result);//preZH-cn-hello-Wordfix
}

reducing及其重载形式,maxBy,minBy

reducing表示对steam里的元素做运算,最终等到一个值。
identity:初值,设置一个steam元素与外部比较的一个初始值。
mapper: 将stream内部类型映射为U类型的方法
BinaryOperator:op两个U类型值合并运算的方法

// 直接对steam里的元素做合并运算,比较类型即为steam里的类型
public static <T> Collector<T, ?, Optional<T>> reducing(BinaryOperator<T> op){
}
// 设置一个初始值,直接对steam里的元素做合并运算
public static <T> Collector<T, ?, T> reducing(T identity, BinaryOperator<T> op){
}
// identity设置一个初始值, mapper将steam里的元素转成合并运算的对象,op合并运算的方法
public static <T, U> Collector<T, ?, U> reducing(U identity, Function<? super T, ? extends U> mapper, BinaryOperator<U> op){
}

示例:

@Test
public void testReducing1() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    Optional<String> op1 = stream.collect(Collectors.reducing((item1, item2) -> {
        if (item1.compareTo(item2) >= 0) {
            return item1;
        } else {
            return item2;
        }
    }));
    System.out.println(op1.get());//hello
}

@Test
public void testReducing2() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    String init = "WWW";
    String s1 = stream.collect(Collectors.reducing(init, (item1, item2) -> {
        if (item1.compareTo(init) > 0) {
            return item1;
        } else {
            return init;
        }
    }));
    System.out.println(s1);//WWW
}

@Test
public void testReducing3() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");

    Person person = new Person();

    Person p1 = stream.collect(Collectors.reducing(
            // 初始值
            person,
            // 将stream内部类型转化成合并运算的对象(Person)
            (item) -> {
                Person personItem = new Person();
                personItem.setName(item);
                personItem.setId(item.length());
                return personItem;
            },
            // 根据转换后的值做合并运算
            (item1, item2) -> {
                if (item1.getId() > item2.getId()) {
                    return item1;
                } else {
                    return item2;
                }
            }
    ));
    System.out.println(p1);//Person(id=5, name=hello)
}

minBy maxBy 就是BinaryOperator提供的简洁方法

@Test
public void testMinBy() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    Optional<String> p1 = stream.collect(Collectors.reducing(BinaryOperator.minBy((item1, item2) -> {
        return item1.compareTo(item2);
    })));
    System.out.println(p1.get());
}

summingLong、summingInt、summingDouble

将steam元素转成long,int,double后做累计

@Test
public void testSummingInt() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    int count = stream.collect(Collectors.summingInt(
            // 将item转成统计维度的数字
            (item) -> {
                return item.length();
            }));
    System.out.println(count);
}

averagingInt/averagingDouble/averagingLong

将steam元素转成long,int,double后做平均值

@Test
public void testAveragingInt() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    double count = stream.collect(Collectors.averagingInt((item)->{
        return item.length();
    }));
    System.out.println(count);
}

summarizingInt/summarizingLong/summarizingDouble

将steam元素转成long,int,double后做统计(最大,最小、平均值)

@Test
public void testSummarizingInt(){
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    IntSummaryStatistics intSummaryStatistics = stream.collect(Collectors.summarizingInt((item)->{
        return item.length();
    }));
    System.out.println(intSummaryStatistics);//IntSummaryStatistics{count=4, sum=13, min=2, average=3.250000, max=5}
}

groupingBy/groupingByConcurrent及其重载形式

将steam元素分组后聚合,API有两种形式

public static <T, K, A, D>
Collector<T, ?, Map<K, D>> groupingBy(Function<? super T, ? extends K> classifier,// 分组结果map的key的生成
                                      Collector<? super T, A, D> downstream) {//分组结果map的value的生成
}

public static <T, K, D, A, M extends Map<K, D>>
    Collector<T, ?, M> groupingBy(Function<? super T, ? extends K> classifier,// 分组结果map的key的生成
                                  Supplier<M> mapFactory,// 分组结果map的生成
                                  Collector<? super T, A, D> downstream) {//分组结果map的value的生成
}

示例:

@Test
public void testGroupingBy1() {
    Stream<String> stream = Stream.of("ZH", "cn", "hello", "Word");
    Map<String, Long> stat = stream.collect(Collectors.groupingBy(
            // key的生成方法
            (item) -> {
                return item.toUpperCase();
            },
            // value的内容
            Collectors.counting()));
    System.out.println(stat);//{WORD=1, HELLO=1, CN=1, ZH=1}
}

@Test
public void testGroupingBy2() {

    List<Person> listPerson = new ArrayList<>();
    listPerson.add(new Person(10, "张三"));
    listPerson.add(new Person(12, "李四"));
    listPerson.add(new Person(14, "王五"));
    listPerson.add(new Person(16, "王麻子"));

    TreeMap obj = listPerson.stream().collect(Collectors.groupingBy(
            // key的生成方法
            (item) -> {
                return item.getName().substring(0, 1);
            },
            // 返回Map的生成方法
            () -> {
                return new TreeMap();
            },
            // Map的Value内容
            Collectors.toList()));

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