프로처럼 Java HashMap 사용하기 (feat. getOrDefault(), computeIfAbsent())

Jiwon Jung·2024년 1월 14일
1
post-custom-banner

Java HashMap에 여러 메소드들이 추가되었고 이런 메소드들을 사용해서 보다 좀 더 효율적이고 프로처럼 사용하는 방법에 대해 알아보겠습니다.


위와같은 해시맵이 있습니다. 만약에 여기세 새로운 key-value ("usa", "los angeles")를 넣으려고 하면 일단 가장 처음 map에 대해 배운 사람이라면 이렇게 쓸 수 있을 것입니다.

String country = "usa";
String city = "los angeles";

// 해당 키가 존자한다면 (존재하는 나라라면)
if(map.containsKey(country)){
  List<String> cities = map.get(country); 
  cities.add(city);
  map.put(country, cities);
} else { // 존재하지 않다면
  List<String> cities = new ArrayList<>();
  cities.add(city);
  map.put(country, cities);
}

이 코드를 좀 더 명확하게 써본다면 다음처럼 개선해볼 수 있겠습니다.

// 새로운 키인 경우 맵에 신규로 등록
if(!map.containsKey(country)){
  map.put(country, new ArrayList<>());
} 
// if 문은 map.get(country)가 null을 반환하기 않도록 함
map.get(country).add(city);

여기서 getOrDefault() 메소드를 사용해서 동일한 기능을 하지만 더 적은 코드로 써보겠습니다.

map.put(country, map.getOrDefault(country, new ArrayList<>());
map.get(country).add(city);

The Tip!

잠시만 멈추고 생각해봅시다. 위 코드를 더 줄여볼 순 없을까요??? 한줄로 써볼 수 없을까요?
computeIfAbset() 라는 메소드를 사용하면 가능합니다!

이 메소드는 2개의 인자를 받습니다.

default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction)
  • key : Map의 키 값
  • mappingFunction
    - mappingFunction 람다 함수는 key 값이 존재하지 않을 때만 실행된다
  • 반환값
    - key 값이 존재하는 경우 map안에 있는 value을 반환한다
    - key 값이 존재하지 않는 경우 Map에 새로운 key와 value(mappingFunction 람다 함수를 실행한 결과) 값을 저장한다

즉, 첫번째 인자로 들어온 key가 map에 존재하지 않는 경우에만 mappingFunction에 의해 새로운 값이 반환되게 됩니다. 이미 key가 존재한다면 해당메소드는 아무것도 하지 않습니다.
(참고로 mappingFunction은 Function이라는 함수형 인터페이스이기에 인자를 받고 하나의 결과값을 리턴해주는 람사표현식으로 사용할 수 있습니다)

computeIfAbsent 메소드를 사용해서 다음처럼 사용해볼 수 있습니다.

map.computeIfAbsent(country, country -> new ArrayList<>()).add(city);

이 메소드와 굉장히 비슷하고 효율적인 또 다른 메소드는 putIfAbsent() 입니다.
이 메소드도 마찬가지고 2개의 인자를 받고, computeIfAgsent() 처럼 key 존재여부에 따라 새로운 key와 value값을 추가합니다.

default V putIfAbsent(K key, V value) 
  • key : Map의 key 값
  • value : value 값
  • 반환 값
    - key 값이 존재하는 경우 Map의 value 값을 반환한다
    - key 값이 존재하지 않는 경우 key와 value를 Map에 저장하고 null을 반환하다

computeIfAbsent() 메소드처럼 key가 맵에 없는 경우라면 새로운 key-value를 넣는 것은 동일하지만 차이는 다음과 같습니다.

  • value값은 key에 의해 연산되지 않습니다.
  • key가 없다면 새로운 key-value페어가 insert 되지만, 그러고나서 해당 메소드는 Null을 반환합니다.

따라서 computeIfAbsent() 때처럼 아래처럼은 할 수 없겠죠. 왜냐하면 key가 없는 경우 null을 리턴할것이고, 이것은 NullPointterException으로 이어지기 때문입니다.

map.putIfAbsent(country, new ArrayList<>()).add(city);

결론

HashMap에 유용한 메소드들이 제공되고 있으니, 무엇이 있는지를 안다면 코드를 짤 때 굉장히 간결하고 가독성 높이는 코드를 작성할 수 있습니다.
다만 비슷해보이는 메소드들이라도 compueIfAbsent()와 putIfAbsent()는 약간의 차이가 있으니 이 부분에 대해서는 좀더 깊이 공부해보고 차이를 안 뒤 사용하면 되겠습니다!

그럼 포스팅은 여기서 마치겠습니다.


Reference

https://medium.com/@ajingnv/a-tip-to-start-using-java-hashmap-like-a-pro-5500cae720fa

profile
게을러지고 싶어 부지런한 개발자
post-custom-banner

1개의 댓글

comment-user-thumbnail
2024년 1월 14일

좋은 글 감사합니다 :)

답글 달기