Lambda使用Stream包下的Collectors的toMap源码分析以及入门案例【第二篇】

本文深入探讨了Java Stream API中的toMap方法,详细解析了如何使用toMap方法收集元素到Map中,包括解决键冲突的方法及自定义合并函数的应用。同时,提供了具体的代码示例和运行结果,帮助读者理解如何在实际场景中正确使用toMap。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

前言

看都看完了,不给个好评吗?点个赞再走也行呀。

返回自己想要的key和value

    /**
     * toMap
     *  TODO
     *     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);
     *     }
     *     @param <T> 输入元素的类型
     *     @param <K> 键映射函数的输出类型
     *     @param <U> 值映射函数的输出类型
     *     @param keyMapper 产生键的映射函数
     *     @param valueMapper 产生值的映射函数
     *     @return a {@code Collector} 收集元素的key和value到一个map中,这个map的key和value是应用映射函数的结果对于输入的元素
     *
     * 如果映射的key 包涵重复会抛出IllegalStateException异常,解决办法使用#toMap(Function, Function, BinaryOperator)}代替
     * 返回的Collector不是并发的,对于并行流管道,Combiner函数通过将键从一个映射合并到另一个映射来进行操作,这将是一个很消耗性能的操作。
     * 如果不需要将结果按遇到的顺序插入到{@code Map}中,则使用{@link #toConcurrentMap(Function,Function)} 可能会提供更好的并行性能。
     *
     */
    @Test
    public void test_toMap_1(){
        List<Student> list = getStudentList();
        list.add(new Student(1, "xixi", 12));
        // java.lang.IllegalStateException: Duplicate key Student(id=1, name=lisi, age=5) 有异常
//        Map<Integer, Student> collect = list.stream().collect(Collectors.toMap(Student::getId, Function.identity()));

        //源码给出的解决办法 key 为ID value为name 对于key相同的value 使用逗号拼接,适用于一个联系人同名,电话不同
        Map<Integer, String> collect_ = list.stream().collect(Collectors.toMap(Student::getId, Student::getName, (s, a) -> s + ", " + a));
        for (Integer key : collect_.keySet()) {
            System.out.println("key: " + key + "====value: " + collect_.get(key));
        }
        System.out.println("'==================='");

        Map<Integer, Student> collect_1 = list.stream().collect(Collectors.toMap(Student::getId, Function.identity(), (a, b) -> a.equals(b) && a.hashCode() == b.hashCode() ? a : b));
        for (Integer key : collect_1.keySet()) {
            System.out.println("key: " + key + "====value: " + collect_1.get(key));
        }
        System.out.println("'==================='");

        // 判断一个对象是否相同equals为true 并且hashcode相同
        Map<Integer, Student> collect_2 = list.stream().collect(Collectors.toMap(Student::getId, Function.identity(), (a, b) -> a.getAge() > b.getAge() ? a : b));
        for (Integer key : collect_2.keySet()) {
            System.out.println("key: " + key + "====value: " + collect_2.get(key));
        }
    }

使用自定义的合并函数以及返回HashMap

    /**
     * toMap
     *  TODO
     *     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);
     *     }
     *     @param <T> 输入元素的类型
     *     @param <K> 键映射函数的输出类型
     *     @param <U> 值映射函数的输出类型
     *     @param keyMapper 产生键的映射函数
     *     @param valueMapper 产生值的映射函数
     *     @param mergeFunction 合并函数,用于解决与同一键关联的值之间的冲突【操作的是值】
     *
     *     如果映射的key有重复的,那么值的映射函数将被应用于每个相等的元素,同一key对应的value结果的合并使用合并的函数
     */
    @Test
    public void test_toMap_2(){
        List<Student> list = getStudentList();
        list.add(new Student(1, "xixi", 12));

        /**
         * 参数一: 是key
         * 参数二: 是value
         * 参数三: 合并函数, 这个是用来解决key相同抛出的非法异常,合并函数操作的是值
         *
         * 以下含义: 生产一个map key 为ID 值为 name 对应相同的key name 使用逗号拼接成value  eg:key: 1====value: lisi, xixi
         */
        Map<Integer, String> collect_ = list.stream().collect(Collectors.toMap(Student::getId, Student::getName, (s, a) -> s + ", " + a));
        for (Integer key : collect_.keySet()) {
            System.out.println("key: " + key + "====value: " + collect_.get(key));
        }
        System.out.println("'==================='");

        /**
         * key 为ID value 为学生对象,对于key 相同的比较两个对象是否完全相同,是返回之前的,不是返回之后的
         */
        Map<Integer, Student> collect_1 = list.stream().collect(Collectors.toMap(Student::getId, Function.identity(), (a, b) -> a.equals(b) && a.hashCode() == b.hashCode() ? a : b));
        for (Integer key : collect_1.keySet()) {
            System.out.println("key: " + key + "====value: " + collect_1.get(key));
        }
        System.out.println("'==================='");
    }

使用自定义的合并函数以及返回自己想要的集合类型

    /**
     * toMap
     *  TODO
     *     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);
     *     }
     *      @param <T> 输入元素的类型
     *      @param <K> 键映射函数的输出类型
     *      @param <U> 值映射函数的输出类型
     *      @param keyMapper 产生键的映射函数
     *      @param valueMapper 产生值的映射函数
     *      @param mergeFunction 合并函数,用于解决与同一键关联的值之间的冲突【操作的是值】
     *      @param mapSupplier 一个新创建的函数,例如返回的结果将被插入到一个空的Map中
     */
    @Test
    public void test_toMap_3(){

        List<Student> list = getStudentList();
        list.add(new Student(1, "xixi", 12));
        /**
         * key 为ID value 为学生对象,对于key 相同的比较两个对象是否完全相同,是返回之前的,不是返回之后的
         */
        Map<Integer, Student> collect_1 = list.stream().collect(Collectors.toMap(Student::getId, Function.identity(), (a, b) -> a.equals(b) && a.hashCode() == b.hashCode() ? a : b, HashMap::new));
        for (Integer key : collect_1.keySet()) {
            System.out.println("key: " + key + "====value: " + collect_1.get(key));
        }
        System.out.println("'==================='");
    }

案例使用的初始化数据

    private List<Student> getStudentList(){
        List<Student> sList = new ArrayList<>();
        sList.add(new Student(1, "lisi", 5));
        sList.add(new Student(2, "wangwu", 7));
        sList.add(new Student(3, "maliu", 9));
        return sList;
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

飞流2023

小主,破费了,回头请你喝咖啡!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值