问题1:如何将自身做为value
//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()));
- 原因:调用了map的merge方法, 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
//List
List<String> list = strings.stream().collect(Collectors.toCollection(LinkedList::new));
//Set
Set<String> set = sets.stream().collect(Collectors.toCollection(TreeSet::new));