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

返回自己想要的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;
    }

在这里插入图片描述

猜你喜欢

转载自blog.csdn.net/wildwolf_001/article/details/103560168
今日推荐