Java8 stream collectingAndThen

介绍

java8 中 collectingAndThen方法的作用是将Collector的结果在执行一个额外的finisher转换操作

    /**
     * Adapts a {@code Collector} to perform an additional finishing
     * transformation.  For example, one could adapt the {@link #toList()}
     * collector to always produce an immutable list with:
     * <pre>{@code
     *     List<String> people
     *         = people.stream().collect(collectingAndThen(toList(), Collections::unmodifiableList));
     * }</pre>
     *
     * @param <T> the type of the input elements
     * @param <A> intermediate accumulation type of the downstream collector
     * @param <R> result type of the downstream collector
     * @param <RR> result type of the resulting collector
     * @param downstream a collector
     * @param finisher a function to be applied to the final result of the downstream collector
     * @return a collector which performs the action of the downstream collector,
     * followed by an additional finishing step
     */
    public static<T,A,R,RR> Collector<T,A,RR> collectingAndThen(Collector<T,A,R> downstream,
                                                                Function<R,RR> finisher) {
        Set<Collector.Characteristics> characteristics = downstream.characteristics();
        if (characteristics.contains(Collector.Characteristics.IDENTITY_FINISH)) {
            if (characteristics.size() == 1)
                characteristics = Collectors.CH_NOID;
            else {
                characteristics = EnumSet.copyOf(characteristics);
                characteristics.remove(Collector.Characteristics.IDENTITY_FINISH);
                characteristics = Collections.unmodifiableSet(characteristics);
            }
        }
        return new CollectorImpl<>(downstream.supplier(),
                                   downstream.accumulator(),
                                   downstream.combiner(),
                                   downstream.finisher().andThen(finisher),
                                   characteristics);
    }
  • T:输入元素的类型
  • A:下游Collector的中间堆积类型
  • R:下游Collector的结果类型
  • RR:结果Collector的结果类型

参数:

  • downstream: Collector的一个实例,可以使用任何Collector
  • finisher: 类型是Function,该函数将应用于下游Collector的最终结果

返回值:返回一个执行下游Collector动作的Collector,然后在finisher函数的帮助下执行附加的转换步骤。

实现

package com.onway.fortunes.shop.tests;

import io.swagger.annotations.ApiModelProperty;
import lombok.AllArgsConstructor;
import lombok.Data;

/***
 * @Author yhj
 * @Date 2021/9/15 0015 上午 10:59
 */
@Data
@AllArgsConstructor
public class UserInfo {

    @ApiModelProperty("姓名")
    private String name;

    @ApiModelProperty("课程")
    private String course;

    @ApiModelProperty("分数")
    private Integer grade;
}

package com.onway.fortunes.shop.tests;

import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.junit.Test;

import java.util.*;
import java.util.stream.Collectors;

/***
 * @Author yhj
 * @Date 2021/9/15 0015 上午 10:57
 */
@Slf4j
public class RemoveRepeatTest extends BaseTest {

    private List<UserInfo> getUserList() {
        List<UserInfo> list = new ArrayList<>();

        UserInfo zhangsan_sx = new UserInfo("zhangsan", "数学", 60);
        UserInfo zhangsan_yw = new UserInfo("zhangsan", "语文", 70);
        UserInfo zhangsan_yy = new UserInfo("zhangsan", "英语", 70);
        UserInfo zhangsan_yy_2 = new UserInfo("zhangsan", "英语", 80);
        UserInfo lisi_sx = new UserInfo("lisi", "数学", 60);
        UserInfo lisi_yw = new UserInfo("lisi", "语文", 70);
        UserInfo lisi_yw_2 = new UserInfo("lisi", "语文", 80);
        UserInfo wangwu_yy = new UserInfo("wangwu", "英语", 70);
        UserInfo wangwu_yy_2 = new UserInfo("wangwu", "英语", 90);

        list.add(zhangsan_sx);
        list.add(zhangsan_yw);
        list.add(zhangsan_yy);
        list.add(zhangsan_yy_2);
        list.add(lisi_sx);
        list.add(lisi_yw);
        list.add(lisi_yw_2);
        list.add(wangwu_yy);
        list.add(wangwu_yy_2);
        return list;
    }

    @Test
    public void userList() {
        List<UserInfo> userList = getUserList();
        log.info("[userList] userList = {}", JSON.toJSONString(userList));
        // 获取集合内每个人出现的次数
        Map<String, Long> counting = userList.stream().collect(
                Collectors.groupingBy(
                        UserInfo::getName, Collectors.counting()
                )
        );
        log.info("[userList] counting = {}", JSON.toJSONString(counting));

        // 根据姓名去重(单字段去重)
        List<UserInfo> singleField = userList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(
                                        Comparator.comparing(UserInfo::getName)
                                )
                        ), ArrayList::new
                )
        );
        log.info("[userList] singleField = {}", JSON.toJSONString(singleField));

        // 根据姓名、学科去重(多字段去重)
        ArrayList<UserInfo> multiField = userList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.toCollection(
                                () -> new TreeSet<>(
                                        Comparator.comparing(
                                                e -> e.getName()
                                                        + ";"
                                                        + e.getCourse()
                                        )
                                )
                        ), ArrayList::new
                )
        );
        log.info("[userList] multiField = {}", JSON.toJSONString(multiField));

        // 查找分数最高 姓名与得分
        String highestScore = userList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.maxBy(
                                Comparator.comparing(
                                        UserInfo::getCourse
                                )
                        ), (
                                Optional<UserInfo> userInfo
                        ) -> userInfo.map(e -> e.getName()
                                + " : "
                                + e.getCourse()
                        ).orElse(null)
                )
        );
        log.info("[userList] highestScore = {}", highestScore);

        // 计算平均分
        Integer average = userList.stream().collect(
                Collectors.collectingAndThen(
                        Collectors.averagingInt(
                                UserInfo::getGrade
                        ), Double::intValue
                )
        );
        log.info("[userList] average = {}", average);
    }
}

输出

[userList] userList = [{"course":"数学","grade":60,"name":"zhangsan"},{"course":"语文","grade":70,"name":"zhangsan"},{"course":"英语","grade":70,"name":"zhangsan"},{"course":"英语","grade":80,"name":"zhangsan"},{"course":"数学","grade":60,"name":"lisi"},{"course":"语文","grade":70,"name":"lisi"},{"course":"语文","grade":80,"name":"lisi"},{"course":"英语","grade":70,"name":"wangwu"},{"course":"英语","grade":90,"name":"wangwu"}]
[userList] counting = {"lisi":3,"zhangsan":4,"wangwu":2}
[userList] singleField = [{"course":"数学","grade":60,"name":"lisi"},{"course":"英语","grade":70,"name":"wangwu"},{"course":"数学","grade":60,"name":"zhangsan"}]
[userList] multiField = [{"course":"数学","grade":60,"name":"lisi"},{"course":"语文","grade":70,"name":"lisi"},{"course":"英语","grade":70,"name":"wangwu"},{"course":"数学","grade":60,"name":"zhangsan"},{"course":"英语","grade":70,"name":"zhangsan"},{"course":"语文","grade":70,"name":"zhangsan"}]
[userList] highestScore = zhangsan : 语文
[userList] average = 72
  • 0
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值