최근에 코드리뷰를 하다가 편리한 기능을 공유하게 되어 간단하게 글로 남겨두면 좋겠다는 생각이 들어 작성하게 되었다. Map 에는 computeIfPresent 와 putIfAbsent 라는 함수가 있다.
일단, 현재 코드는 다음과 같다.
protected Map<String, List<String>> separateMessageId(List<M> models) {
Map<String, List<String>> messageIdentity = new HashMap<>();
for (M message : models) {
if (messageIdentity.containsKey(message.getCwAppId())) {
messageIdentity.get(message.getCwAppId()).add(message.getMessageId());
continue;
}
messageIdentity.put(message.getCwAppId(), new ArrayList() {{ add(message.getMessageId()); }});
}
return messageIdentity;
}
Java
복사
변경전 코드
로직은 다음과 같다.
1.
ID에 해당하는 key, value 가 map 에 있는지 확인한다.
2.
없으면 put(key, List<value>) 를 수행한다.
3.
있으면 value list에 현재 value 를 추가한다.
사실 크게 이상할 것은 없다.
하지만, 새로 추가된 함수를 다음과 같이 작성하면 더 편리해진다.
protected Map<String, List<String>> separateByCwAppId(List<M> models) {
Map<String, List<String>> messagesByCwAppId = new HashMap<>();
for (M message : models) {
messagesByCwAppId.computeIfPresent(message.getCwAppId(), (key, value) -> {
value.add(message.getMessageId());
return value;
});
messagesByCwAppId.putIfAbsent(message.getCwAppId(), new ArrayList() {{ add(message.getMessageId()); }});
}
return messagesByCwAppId;
}
Java
복사
변경한 코드
여기서 중요한 것은 computeIfPresent 와 putIfAbsent 의 순서를 변경하면 안된다.
코드를 읽어보면 알겠지만, 없어서 key 와 list 를 put 하고, 다시 add 를 해주는 일이 생긴다.
computeIfPresent
JDK11 기준으로 computeIfPresent 의 함수는 아래와 같다.
default V computeIfPresent(K key,
BiFunction<? super K, ? super V, ? extends V> remappingFunction) {
Objects.requireNonNull(remappingFunction);
V oldValue;
if ((oldValue = get(key)) != null) {
V newValue = remappingFunction.apply(key, oldValue);
if (newValue != null) {
put(key, newValue);
return newValue;
} else {
remove(key);
return null;
}
} else {
return null;
}
}
Java
복사
•
BiFunction 은 두개의 input을 받아 1개의 result 를 반환한다.
•
key 에 해당하는 value 가 없다면 함수는 null 을 반환한다.
•
key 에 해당하는 value 가 있다
◦
새로운 value가 null이 아니면 새로운 value 를 put 하고, 새로운 value를 반환한다.
◦
새로운 value가 null 이면, key, value 를 제거하고, null 을 반환한다.
putIfAbsent
JDK 11 기준으로 putIfAbsent 의 구현은 아래와 같다.
default V putIfAbsent(K key, V value) {
V v = get(key);
if (v == null) {
v = put(key, value);
}
return v;
}
Java
복사
•
무조건 value 를 반환한다.
•
Map에 저장된 key 가 없어야 동작한다.
주의할 점
default 구현은 모두 Map 안에 있는 구현이다.
따라서, thread-safe 같은 기능은 존재하지 않으므로 이러한 기능이 필요하다면 알맞은 구현체를 선택해야 한다.