IT/개발로그

[Java] List -> Map 변환은 신중하자

김솔샤르 2022. 5. 29. 18:31

List를 Map으로 변형해야할 일이 있어서 이렇게 처리했다고 해보자.

List<Food> foods = Arrays.asList(
		new Food("Coke", 1500),
		new Food("Beer", 3000),
		new Food("Coke", 1600),
		new Food("Snack", 4000));

Map<String, Integer> foodMap = foods.stream()
		.collect(Collectors.toMap(Food::getName, Food::getPrice));


코드를 실행하보면 Duplicate Key 예외가 발생한다. 위 예제야 뻔히 보이지만 수천, 수만건의 데이터 중 단 하나의 중복이 있었다면 사전에 발견하지 못했을 것이다. 비즈니스적으로는 중복이 없어야 맞는 것이라도, 예상할 수 없었던 예외 케이스가 늘 발생할 수 있고 테스트 시점에서는 이를 간과하기도 쉽다.

따라서 아래와 같이 방어적으로 중복 처리 코드를 넣는 것이 현명하다.

List<Food> foods = Arrays.asList(
		new Food("Coke", 1500),
		new Food("Beer", 3000),
		new Food("Coke", 1600),
		new Food("Snack", 4000));
        
Map<String, Long> foodMap = new HashMap<>();

foods.forEach(food -> foodMap.merge(
		food.getName(),
		food.getPrice(),
      	     	(food1, food2) -> {
                    log.error("There is duplicate key! food name : {}", food.getName());
                    return food2;
          	}));

스트림을 쓰면 좋겠지만 Collectors.toMap의 mergeFunction 인터페이스에서는 key를 알아낼 방법이 없다. 아무튼 Key 중복이 발생하는 경우에는 순서적으로 뒤에 있는 객체를 선택하도록 방어 로직을 넣고, 에러 로그를 찍었다. 후에 로그를 보면서 어떤 데이터가 잘못되었는지 분석할 수 있을 것이다.

경우에 따라서는 그냥 예외를 발생시키고 프로그램을 끝내는 것이 비즈니스적으로 옳을 수도 있다. 어찌됐든 List -> Map과 같은 자료구조 변형시에는 이런 예외 케이스가 늘 발생할 수 있음을 생각하고 신중하자.

반응형