다음과 같은 데이터를 요청받거나 DB에서 조회한다고 가정하자.
사원목록과 직급정보를 JSON형태로 표현하였다.
{ "empList": [ { "empNo": "3278", "name": "김철수", "rankId": "3" }, { "empNo": "2457", "name": "안영희", "rankId": "2" }, { "empNo": "6323", "name": "고민수", "rankId": "1" }, { "empNo": "7342", "name": "황동석", "rankId": "2" }, { "empNo": "4215", "name": "김가영", "rankId": "1" } ], "rankList": [ { "rankId": "1", "name": "과장" }, { "rankId": "2", "name": "대리" }, { "rankId": "3", "name": "사원" } ] }
어플리케이션단에서 해당 정보를 가지고 직급아이디(rankId)가 아닌 직급명(rankName)으로 사원목록을 표현하고 싶다면 어떻게 코드를 짜야할까?
ObjectMapper objectMapper = new ObjectMapper();
List<Map<String, String>> empList = (List<Map<String, String>>) objectMapper.readValue(jsonStr, Map.class).get("empList");
List<Map<String, String>> rankList = (List<Map<String, String>>) objectMapper.readValue(jsonStr, Map.class).get("rankList");
먼저 jackson라이브러리의 ObjectMapper통해 json데이터를 단순히 리스트<맵> 형태로 담아보았다.
이중 for문 사용
for (Map<String, String> empMap : empList) { for (Map<String, String> rankMap : rankList) { if (empMap.get("rankId").equals(rankMap.get("rankId"))) { empMap.put("rankName", rankMap.get("name")); } } empMap.remove("rankId"); }
코드를 보면 알겠지만 for문을 이중으로 돌려 각 사원정보를 참조할때마다 직급정보를 한번더 순회하여 데이터를 붙이는 방식이다.
보통 이런 형태로 2중 for문을 사용하는 코드는 시간복잡도를 늘리는 등 지양하는 편이다.
그럼 어떤 코드를 작성하면 좋을까?
List를 Map으로 변환 후 for문 한번 돌리기
Map<String, Map<String, String>> rankMap = rankList.stream().collect(Collectors.toMap(i -> i.get("rankId"), i -> i)); for (Map<String, String> empMap : empList) { empMap.put("rankName", rankMap.get(empMap.get("rankId")).get("name")); empMap.remove("rankId"); }
stream의 collector를 사용하여 타겟데이터의 list를 Map으로 변환후 for문 한번으로 각 key를 참조하여 필요한 데이터를 Map에서 가지고와 데이터 붙이는 방식이다.
이런 방식이면 for문 한번으로도 원하는 형태의 데이터를 반환할 수 있다.
직급ID에서 직급명 형태로 표현한 사원목록 json 데이터
[ { "empNo": "3278", "name": "김철수", "rankName": "사원" }, { "empNo": "2457", "name": "안영희", "rankName": "대리" }, { "empNo": "6323", "name": "고민수", "rankName": "과장" }, { "empNo": "7342", "name": "황동석", "rankName": "대리" }, { "empNo": "4215", "name": "김가영", "rankName": "과장" } ]