Loading

Java8 collect toMap问题

问题1:如何将自身做为value

  • 解决:Function.identity()
//Function.identity()将IndexMetricsTrendRowVO作为value
Map<String, IndexMetricsTrendRowVO> rowMap = trendRows.stream().collect(Collectors.toMap(IndexMetricsTrendRowVO::getDateTime, Function.identity()));

问题2:value为null报NPE

Map<String, Field> fieldMap = allFieldsList.stream().collect(Collectors.toMap(Field::getName, Function.identity()));
  • 原因:调用了mapmerge方法, HashMap::merge方法会对value判断为null,默认的merge函数也会Objects.requireNonNull判断
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);
}

@Override
public V merge(K key, V value,
               BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    if (value == null)
        throw new NullPointerException();
    ...
}

default V merge(K key, V value,
                BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    Objects.requireNonNull(remappingFunction);
    Objects.requireNonNull(value);
    V oldValue = get(key);
    V newValue = (oldValue == null) ? value :
    remappingFunction.apply(oldValue, value);
    if(newValue == null) {
        remove(key);
    } else {
        put(key, newValue);
    }
    return newValue;
}
  • 解决:自定义一个collect收集器,自定义mergeFunction为HashMap::putAll
Map<String, IndexMetricsRowVO> rowMap = trendRows.stream().collect(HashMap::new, (map, row) -> map.put(row.getXaxis(), row), HashMap::putAll);

问题3:toMap报java.lang.IllegalStateException: Duplicate key

  • 原因:有重复的key,使用了默认的mergeFunction,默认mergeFunction抛出异常
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);
}

//mergeFunction在merge方法中使用
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);
}

//HashMap::merge方法中的remappingFunction
@Override
public V merge(K key, V value,
               BiFunction<? super V, ? super V, ? extends V> remappingFunction) {
    if (value == null)
        throw new NullPointerException();
    if (remappingFunction == null)
        throw new NullPointerException();

    ......
       
    //通过key查到已经有值
    if (old != null) {
        V v;
        if (old.value != null)
         	//apply方法
            v = remappingFunction.apply(old.value, value);
        else
            v = value;
        if (v != null) {
            old.value = v;
            afterNodeAccess(old);
        }
        else
            removeNode(hash, key, null, false, true);
        return v;
    }
    ......
}

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

  • 解决:参照问题2,自定义mergeFunction

问题4:使用其他类型的List, Set, Map

  • 解决:自定义Supplier
//List
List<String> list = strings.stream().collect(Collectors.toCollection(LinkedList::new));

//Set
Set<String> set = sets.stream().collect(Collectors.toCollection(TreeSet::new));
posted @ 2022-01-06 09:55  FynnWang  阅读(228)  评论(0编辑  收藏  举报