解决Java 8 Collectors.toMap将抛出一个NullPointerException

x33g5p2x  于2021-08-12 发布在 Java  
字(2.5k)|赞(0)|评价(0)|浏览(426)

使用Collectors.toMap时,若value值为null,报NullPointerException。

报错代码

public static <T, K, U> Map<K, U> toMap(Collection<T> collection, Function<? super T, ? extends K> keyMapper,
                                            Function<? super T, ? extends U> valueMapper)
    {
        if (StreamUtil.isEmpty(collection)) {
            return new HashMap<>(1);
        }
        return collection.stream().collect(Collectors.toMap(keyMapper, valueMapper, (oldValue, newValue) -> newValue));
    }

报错原因

使用Collectors.toMap时,当key重复时,在新值和旧值合并方法中,要求新值不能为null。
接口Map<K,V> merge方法的源码:

default V merge(K key, V value, BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
		/** 问题所在 */
        Objects.requireNonNull(value);

        while(true) {
            Object oldValue = this.get(key);

            while(oldValue == null) {
                if ((oldValue = this.putIfAbsent(key, value)) == null) {
                    return value;
                }
            }

            V newValue = remappingFunction.apply(oldValue, value);
            if (newValue != null) {
                if (this.replace(key, oldValue, newValue)) {
                    return newValue;
                }
            } else if (this.remove(key, oldValue)) {
                return null;
            }
        }
    }

解决方法

public class CollectorUtils {
    /**
     * 与默认的java不同,当你有null值时,它不会出现异常
     * 解决Java 8 Collectors.toMap将抛出一个NullPointerException
     */
    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());
    }

    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);
    }

    /**
     * 与默认的java不同,当你有null值时,它不会出现异常
     */
    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,
                                                                          Supplier<M> mapSupplier) {
        return toMap(keyMapper, valueMapper, throwingMerger(), mapSupplier);
    }

    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) {
        return Collectors.collectingAndThen(
                Collectors.toList(),
                list -> {
                    M result = mapSupplier.get();
                    for (T item : list) {
                        K key = keyMapper.apply(item);
                        U value = valueMapper.apply(item);
                        U oldValue;
                        if ((oldValue = result.put(key, value)) != null) {
                            result.put(key, mergeFunction.apply(oldValue, value));
                        }
                    }
                    return result;
                });
    }

    private static <T> BinaryOperator<T> throwingMerger() {
        return (u, v) -> {
            throw new IllegalStateException(String.format("Duplicate key %s", u));
        };
    }
}

相关文章

热门文章

更多