解决Stream Collectors.toMap 当value为null时报空指针问题

问题

Stream Collectors.toMap 当value为null时报空指针,如下图所示:

public class Demo {
    public static void main(String[] args) {
        List<Test> list = new ArrayList<>();
        list.add(new Test("code1", "name1"));
        list.add(new Test("code2", null));
        Map<String, String> map = list.stream().collect(Collectors.toMap(Test::getCode, Test::getName));
        System.out.println(map);
    }
}

@Data
@AllArgsConstructor
class Test {
    private String code;
    private String name;
}

执行结果:

Exception in thread "main" java.lang.NullPointerException
	at java.util.HashMap.merge(HashMap.java:1226)
	at java.util.stream.Collectors.lambda$toMap$58(Collectors.java:1320)
	at java.util.stream.ReduceOps$3ReducingSink.accept(ReduceOps.java:169)
	at java.util.ArrayList$ArrayListSpliterator.forEachRemaining(ArrayList.java:1384)
	at java.util.stream.AbstractPipeline.copyInto(AbstractPipeline.java:482)
	at java.util.stream.AbstractPipeline.wrapAndCopyInto(AbstractPipeline.java:472)
	at java.util.stream.ReduceOps$ReduceOp.evaluateSequential(ReduceOps.java:708)
	at java.util.stream.AbstractPipeline.evaluate(AbstractPipeline.java:234)
	at java.util.stream.ReferencePipeline.collect(ReferencePipeline.java:566)
	at com.scj.test.Demo.main(Demo.java:15)

底层源码:

public final class Collectors {
    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);
    }

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

Collectors.toMap 最终会调用 Map 的 merge 方法,这里会对value进行判空,如果为空,则抛出空指针异常。

public interface Map<K,V> {
    default V merge(K key, V value,
                    BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
        Objects.requireNonNull(remappingFunction);
        Objects.requireNonNull(value);	// 这里会对value判空,如果为空,则抛出NPE
        V oldValue = get(key);
        V newValue = (oldValue == null) ? value :
        remappingFunction.apply(oldValue, value);
        if(newValue == null) {
            remove(key);
        } else {
            put(key, newValue);
        }
        return newValue;
    }
}

解决

  • 方案一:采用下面这种写法
Map<String, String> collect = list.stream().collect(
    HashMap::new, 
    (m, v) -> m.put(v.getCode(), v.getName()), 
    HashMap::putAll
);
  • 方案二:对value进行判空,并给一个默认值
Map<String, String> map = list.stream().collect(Collectors.toMap(
    Test::getCode, 
    e -> Optional.ofNullable(e.getName()).orElse("")
));
  • 2
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值