[Java8] HashMap 메서드 파헤치기

채희승·2022년 7월 4일
0

Junit을 이용해 자바8부터 추가된 HashMap의 메서드를 더 간결하고 효율적으로 사용하는 방법을 익히고자 작성한 테스트 코드입니다.

  • putIfAbsent()
  • computeIfAbsent()
  • compute()
  • computeIfPresent()
  • merge()
  • getOrDefault()
package map;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.jupiter.api.Assertions.assertEquals;

import java.util.HashMap;
import java.util.Map;

class Test {
	
	// 자바8 HashMap 보다 간결하고 효과적으로 작성하기
	// https://blog.advenoh.pe.kr/java/%EC%9E%90%EB%B0%948-HashMap-%EB%B3%B4%EB%8B%A4-%EA%B0%84%EA%B2%B0%ED%95%98%EA%B3%A0-%ED%9A%A8%EA%B3%BC%EC%A0%81%EC%9C%BC%EB%A1%9C-%EC%9E%91%EC%84%B1%ED%95%98%EA%B8%B0/
	// https://rian-yeji.github.io/algorithm/2019/07/09/algorithm-hashmap-basic.html
	
	/*
	 * default V putIfAbsent(K key, V value);
	 * 
	 * - key: Map의 key 값
	 * - value: value 값
	 * - 반환값: 
	 * 		- key값이 존재하는 경우 Map의 value값을 반환한다. 
	 * 		- key값이 존재하지 않는 경우 key와 value를 Map에 저장하고 null을 반환한다.
	 */
	@org.junit.jupiter.api.Test
	void putIfAbsent() {
		Map<String, Integer> map = new HashMap<>();
		map.put("John", 5);
		
		assertEquals(map.putIfAbsent("John", 10), 5); // 존재하는 경우, value값을 반환한다.
		assertEquals(map.size(), 1);
		
		assertNull(map.putIfAbsent("John2", 10)); // 없는 경우, null로 반환하고 map에 저장함.
		assertEquals(map.size(), 2);
		
		// {John2=10, John=5}
		// System.out.println(map.toString());
	}
	
	/*
	 * default V computeIfAbsent(K key, Function<? super K, ? extends V> mappingFunction);
	 * 
	 * - key: Map의 key 값
	 * - mappingFunction: mappingFunction 람다 함수는 key 값이 존재하지 않을 때만 실행된다.
	 * - 반환값: 
	 * 		- key값이 존재하는 경우 Map의 value값을 반환한다. 
	 * 		- key값이 존재하지 않는 경우 Map에 새로운 key와 value(mappingFunction 람다 함수를 실행한 결과) 값을 저장한다.
	 */
	@org.junit.jupiter.api.Test
	void computeIfAbsent() {
		Map<String, Integer> map = new HashMap<>();
		map.put("John", 5);
		
		assertEquals(map.computeIfAbsent("John", key -> key.length()), 5); // 존재하면 value값을 반환함.
		assertEquals(map.size(), 1);
		
		// 없으면 2번째 인자 함수를 실행한 결과를 반환하고 map에도 추가가 된다.
		assertEquals(map.computeIfAbsent("John2", key -> key.length()), "John2".length());
		assertNotNull(map.get("John2"));
		assertEquals(map.size(), 2);
		
		assertNull(map.computeIfAbsent("John3", key -> null));
		assertEquals(map.size(), 2);
		
		// {John2=5, John=5}
		// System.out.println(map.toString());
	}
	
	/*
	 * default V compute(K key, 
	 * 	BiFunction<? super K, ? super V, ? extends V> remappingFunction);
	 * 
	 * compute는 key와 remappingFunction을 인자로 받고 key가 존재해야 
	 * value 값을 인자로 넘겨준 remappingFunction 람다 함수의 결과로 업데이트가 된다. 
	 * key 값이 존재하지 않는 경우에는 NullPointerException이 발생.
	 * 
	 */
	@org.junit.jupiter.api.Test
	void compute() {
		Map<String, Integer> map = new HashMap<>();
		map.put("apple", 10);
		map.put("orange", 20);
		map.put("mango", 30);
		
		Integer resultValue = map.compute("mango", (k, v) -> v + 50);
		// System.out.println(resultValue); // 80
		assertEquals(map.get("mango"), 30 + 50);	
		
		//map.compute("banana", (k, v) -> v + 50); // key값이 존재하지 않으므로 NPE발생.
		assertNull(map.get("banana"));
	}
	
	/*
	 * default V compute(K key, 
	 * 	BiFunction<? super K, ? super V, ? extends V> remappingFunction);
	 * 
	 * - 반환값: 
	 * 		- key값이 존재하는 경우 remappingFunction 람다 함수 실행결과로 value값이 업데이트된다. 
	 * 		- key값이 존재하지 않는 경우 null을 반환한다.
	 * 
	 */
	@org.junit.jupiter.api.Test
	void computeIfPresent() {
		Map<String, Integer> map = new HashMap<>();
		map.put("apple", 10);
		map.put("orange", 20);
		map.put("mango", 30);
		
		map.computeIfPresent("test", (k, v) -> v + 10); // key가 존재하지 않으므로 null을 반환.
		assertNull(map.get("test"));
		
		map.computeIfPresent("mango", (k, v) -> v + 10);
		assertEquals(map.get("mango"), 30 + 10);
	}
	
	/*
	 * default V merge(K key, V value, 
	 * 	BiFunction<? super K, ? super V, ? extends V> remappingFunction);
	 * 
	 * - 반환값: 
	 * 		- key값이 존재하는 경우 
	 * 			- Case1: remappingFunction 함수 결과가 null이 아니면, 람다 함수 실행결과로 value가 업데이트 된다.
	 * 			- Case2: remappingFunction 함수 결과가 null이면, map에서 해당 key를 삭제한다.
	 * 		- key값이 존재하지 않는 경우 Map에 key, value 값이 추가된다.
	 * 
	 */
	@org.junit.jupiter.api.Test
	void merge() {
		Map<String, Integer> map = new HashMap<>();
		map.put("apple", 10);
		map.put("orange", 20);
		map.put("mango", 30);
		
		// key값이 존재를 하면, 해당 key의 값을 remapping 함수의 결과 값으로 바꾼다.
		map.merge("mango", 40, (k, v) -> map.get("apple") + 100);
		assertEquals(map.get("mango"), 110);
		
		// key가 존재하고 remapping 함수의 결과가 null이면 map에서 해당 key를 삭제한다.
		map.merge("mango", 30, (k, v) -> map.get("banana"));
		assertNull(map.get("mango"));
		assertEquals(map.size(), 2);
		
		// key가 존재하지 않으면, key, value값을 추가함.(두번째 인자 값을 사용)
		map.merge("banana", 40, (k, v) -> map.get("apple") + 120);
		assertEquals(map.get("banana"), 40);
		assertEquals(map.size(), 3);
		
		System.out.println(map.toString());
	}

	/*
	 * default V getOrDefault(Object key, V defaultValue)
	 * 
	 * - 반환값: 
	 * 		- key값이 존재하는 경우 Map의 value값을 반환한다.
	 * 		- key값이 존재하지 않는 경우 defaultValue를 반환한다.
	 * 
	 */
	@org.junit.jupiter.api.Test
	void getOrDefault() {
		String str = "test";
		Map<Character, Integer> map1 = new HashMap<>();
		Map<Character, Integer> map2 = new HashMap<>();
		
		// getOrDefault를 사용하지 않는 경우
		for (char c : str.toCharArray()) {
			if (map2.containsKey(c)) 
				map2.put(c, map2.get(c) + 1);
			else
				map2.put(c, 1);
		}
		
		// getOrDefault를 사용하는 경우
		for (char c : str.toCharArray()) {
			map1.put(c, map1.getOrDefault(c, 0) + 1);
		}
		
		assertEquals(map1, map2);
		
		// {s=1, t=2, e=1}
//		System.out.println(map1.toString());
//		System.out.println(map2.toString());
	}
}
profile
느릴지언정 정도(正道)를

0개의 댓글