Java8 Collectors.toMap异常解析

本文涉及的产品
公共DNS(含HTTPDNS解析),每月1000万次HTTP解析
全局流量管理 GTM,标准版 1个月
云解析DNS,个人版 1个月
简介: Java8 Collectors.toMap异常解析

一 故事背景

今天乐乐和同事们一起发现了一个异常

Exception in thread "main" java.lang.IllegalStateException: Duplicate key

引发异常的代码原因是Collectors.toMap中出现了重复的key, 于是乐乐为了研究问题的发生原因自己开始撸代码测试

二 异常分析

乐乐首先创建了一个集合用于测试

List list = Lists.newArrayList();
list.add("3");
list.add("4");
list.add("5");
list.stream().forEach(s-> System.out.println(s));

乐乐发现有另外一种更简便的方式创建集合

 Arrays.asList("3","4","5").stream().forEach(s-> System.out.println(s));

简洁了不少,但是乐乐突然又发现还有比这种还简洁的

 Stream.of("3","4","5").forEach(s-> System.out.println(s));
 

接着我们看一下上面的问题

 Map collect = Stream.of("a", "b", "c", "a").collect(Collectors.toMap(x -> x, x -> x + x));
collect.forEach((k,v) -> System.out.println(k + ":" + v));

执行这段代码机会发生上面的异常,如何解决呢?

三 解决方案

增加合并函数,合并函数是什么呢?看下源码调用

public static Collector<T, ?, Map> toMap(Function keyMapper,
                                Function valueMapper,
                                BinaryOperator mergeFunction) {
    return toMap(keyMapper, valueMapper, mergeFunction, HashMap::new);
}

BinaryOperator mergeFunction 就是合并函数

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
    /**
     * Returns a {@link BinaryOperator} which returns the lesser of two elements
     * according to the specified {@code Comparator}.
     *
     * @param <T> the type of the input arguments of the comparator
     * @param comparator a {@code Comparator} for comparing the two values
     * @return a {@code BinaryOperator} which returns the lesser of its operands,
     *         according to the supplied {@code Comparator}
     * @throws NullPointerException if the argument is null
     */
    public static <T> BinaryOperator<T> minBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) <= 0 ? a : b;
    }

    /**
     * Returns a {@link BinaryOperator} which returns the greater of two elements
     * according to the specified {@code Comparator}.
     *
     * @param <T> the type of the input arguments of the comparator
     * @param comparator a {@code Comparator} for comparing the two values
     * @return a {@code BinaryOperator} which returns the greater of its operands,
     *         according to the supplied {@code Comparator}
     * @throws NullPointerException if the argument is null
     */
    public static <T> BinaryOperator<T> maxBy(Comparator<? super T> comparator) {
        Objects.requireNonNull(comparator);
        return (a, b) -> comparator.compare(a, b) >= 0 ? a : b;
    }
}

他继承了另一个函数式接口

@FunctionalInterface
public interface BiFunction<T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);

    /**
     * Returns a composed function that first applies this function to
     * its input, and then applies the {@code after} function to the result.
     * If evaluation of either function throws an exception, it is relayed to
     * the caller of the composed function.
     *
     * @param <V> the type of output of the {@code after} function, and of the
     *           composed function
     * @param after the function to apply after this function is applied
     * @return a composed function that first applies this function and then
     * applies the {@code after} function
     * @throws NullPointerException if after is null
     */
    default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
        Objects.requireNonNull(after);
        return (T t, U u) -> after.apply(apply(t, u));
    }
}

java8中接口不只只有default方法可以写实现,stastic方法也可以写实现。

回到合并函数,合并函数可以让map不出现重复的key值,所以不回报错,但是他本身会改变key值这一点是要十分小心的。

修改后

Map collect = Stream.of("a", "b", "c", "a").collect(Collectors.toMap(x -> x, x -> x + x,(oldVal, newVal) -> newVal));
相关文章
|
7天前
|
Java 数据库连接 开发者
Java中的异常处理机制深度解析
【8月更文挑战第13天】本文旨在深入探讨Java编程语言中一个至关重要的组成部分——异常处理机制。我们将从基本概念入手,逐步展开讨论异常处理在Java语言设计中的角色和重要性,以及如何正确利用这一机制来提高代码的健壮性和可维护性。文章将通过分析异常处理的最佳实践,揭示如何在复杂的应用程序中有效地管理和处理错误情况。
|
4天前
|
JSON 前端开发 Java
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
【8月更文挑战第12天】SpringBootWeb极速入门-请求参数解析(02)
10 1
【前端学java】SpringBootWeb极速入门-请求参数解析(02)
|
3天前
|
自然语言处理 Java 应用服务中间件
Java 18 新特性解析
Java 18 新特性解析
|
3天前
|
存储 设计模式 Java
Java中的if-else语句:深入解析与应用实践
Java中的if-else语句:深入解析与应用实践
|
3天前
|
Java 索引
Java中的for循环:深度解析
Java中的for循环:深度解析
|
4天前
|
存储 Java 程序员
|
3天前
|
设计模式 存储 Java
掌握Java设计模式的23种武器(全):深入解析与实战示例
掌握Java设计模式的23种武器(全):深入解析与实战示例
|
3天前
|
算法 安全 Java
深入解析Java多线程:源码级别的分析与实践
深入解析Java多线程:源码级别的分析与实践
|
15天前
|
存储 NoSQL Redis
redis 6源码解析之 object
redis 6源码解析之 object
43 6
|
7天前
|
开发者 Python
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
深入解析Python `httpx`源码,探索现代HTTP客户端的秘密!
31 1

热门文章

最新文章

推荐镜像

更多