아래와 같은 toMap 코드를 사용하면 NPE 에러가 발핸다.
final Map<String, Object> valueMap = pingFailedHosts
.stream()
.collect(Collectors.toMap(c->c, null));
toMap 메소드는 KeyMapper와 ValueMapper를 전달하는 형태인데.
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);
}
toMap 원형 함수를 보면, mergeFunction , 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) {
BiConsumer<M, T> accumulator
= (map, element) -> map.merge(keyMapper.apply(element),
valueMapper.apply(element), mergeFunction);
return new CollectorImpl<>(mapSupplier, accumulator, mapMerger(mergeFunction), CH_ID);
}
https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html
toMap 메소드의 매개변수를 보면, mergeFunction이 Map.merge()와 연관되어 있음을 알 수 있다.
keyMapper
- a mapping function to produce keysvalueMapper
- a mapping function to produce valuesmergeFunction
- a merge function, used to resolve collisions between values associated with the same key, as supplied to Map.merge(Object, Object, BiFunction)
mapSupplier
- a function which returns a new, empty Map
into which the results will be inserted코드를 따라가 들어가면
private static <K, V, M extends Map<K,V>>
BinaryOperator<M> mapMerger(BinaryOperator<V> mergeFunction) {
return (m1, m2) -> {
for (Map.Entry<K,V> e : m2.entrySet())
m1.merge(e.getKey(), e.getValue(), mergeFunction);
return m1;
};
}
m1.merge() 메소드가 바로 Map.merge() 메소드이다.
여기 코드 보면, value 값이 not null이어야 한다.
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;
}
코드의 주석이나, 오라클 javadoc 문서를 보면 역시 NPE를 발행하는 코드임을 확인할 수 있다.
NullPointerException
- if the specified key is null and this map does not support null keys or the value or remappingFunction is null
따라서 key나 value의 값이 null일 확률이 높다면, toMap()를 사용하지 말아야 한다.
아래와 같이 naive하게 개발하는 것이 좋다.
final Map<String, String> valueMap2 = Arrays.asList("cacti.google.com", "sun.google.com")
.stream()
.collect(HashMap::new, (m,v)->m.put(v, null), HashMap::putAll);
'java core' 카테고리의 다른 글
[java] ubuntu에서 java10 설치 (0) | 2018.06.19 |
---|---|
자바 heap 튜닝/분석할 때 주의할 점 (0) | 2018.05.30 |
[펌] java8의 parrallel stream 좋은 설명 (0) | 2018.03.08 |
[java] Date를 GMT스타일(is8601)로 변환하는 방법 - 또는 그 반대로 변환 방법 예제 (0) | 2018.01.19 |
[jvm] gc 로그와 메모리 (0) | 2018.01.14 |