프로그래머스를 통해 알고리즘 공부를 하던 중 Map의 Value를 정렬해야 했다.
내가 생각한 방법은 두가지였으며 아래와 같다.
1. Comparator를 이용한 정렬
2. Stream을 이용한 정렬
문제는 아래 링크를 참조
https://programmers.co.kr/learn/courses/30/lessons/42579
1. Comparator를 이용한 정렬
- 소스
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
int[] answer = {};
/* 2021-06-07 Map안에 Map 사용 */
Map<String, Map<Integer, Integer>> map = new HashMap<String, Map<Integer,Integer>>(); // 장르별 Map<고유번호, 플레이수>
Map<String, Integer> totalPlayMap = new HashMap<>(); // 장르별 플레이수 총합
// 데이터 적재
for(int i=0; i<genres.length; i++) {
if(map.containsKey(genres[i])) {
map.get(genres[i]).put(i, plays[i]);
} else {
Map<Integer, Integer> temp = new HashMap<Integer, Integer>();
temp.put(i, plays[i]);
map.put(genres[i], temp);
}
totalPlayMap.put(genres[i], totalPlayMap.getOrDefault(genres[i], 0)+plays[i]);
}
/* 2021-06-09 */
// 총 플레이수가 높은 순서대로 장르 정렬
List<String> keySetList = new ArrayList<String>(totalPlayMap.keySet());
// 내림차순 정렬
Collections.sort(keySetList, new Comparator<String>() {
@Override
public int compare(String o1, String o2) {
return totalPlayMap.get(o2).compareTo(totalPlayMap.get(o1));
}
});
List<Integer> answerList = new ArrayList<Integer>();
// 우선순위 장르별 상위 플레이수 정렬 및 상위 2개 추출
for(String key : keySetList) {
List<Integer> playKeyList = new ArrayList<Integer>(map.get(key).keySet());
Collections.sort(playKeyList, new Comparator<Integer>() {
@Override
public int compare(Integer o1, Integer o2) {
return map.get(key).get(o2).compareTo(map.get(key).get(o1));
}
});
int j=0;
for(Integer itg : playKeyList) {
answerList.add(itg);
if(++j>=2) break;
}
}
answer = new int[answerList.size()];
for(int k=0; k<answer.length; k++) {
answer[k] = answerList.get(k);
}
return answer;
}
}
- 테스트 결과
2. Stream을 이용한 정렬
- 소스
import java.util.*;
class Solution {
public int[] solution(String[] genres, int[] plays) {
int[] answer = {};
/* 2021-06-07 Map안에 Map 사용 */
Map<String, Map<Integer, Integer>> map = new HashMap<String, Map<Integer,Integer>>(); // 장르별 Map<고유번호, 플레이수>
Map<String, Integer> totalPlayMap = new HashMap<>(); // 장르별 플레이수 총합
// 데이터 적재
for(int i=0; i<genres.length; i++) {
if(map.containsKey(genres[i])) {
map.get(genres[i]).put(i, plays[i]);
} else {
Map<Integer, Integer> temp = new HashMap<Integer, Integer>();
temp.put(i, plays[i]);
map.put(genres[i], temp);
}
totalPlayMap.put(genres[i], totalPlayMap.getOrDefault(genres[i], 0)+plays[i]);
}
/* 2021-06-11 Map 정렬 람다식으로 변경 */
List<Integer> answerList = new ArrayList<Integer>();
totalPlayMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder()))
.forEach(x -> {
String tempKey = x.getKey();
Map<Integer, Integer> tempMap = map.get(tempKey);
tempMap.entrySet().stream().sorted(Map.Entry.comparingByValue(Comparator.reverseOrder())).limit(2)
.forEach(y -> {
answerList.add(y.getKey());
});
});
answer = new int[answerList.size()];
for(int k=0; k<answer.length; k++) {
answer[k] = answerList.get(k);
}
return answer;
}
}
- 테스트 결과
> 결론
Stream을 이용한 정렬을 사용한 코드로 변경하고 나서 코드는 짧아졌지만,
Java 8부터 제공되는 Stream은 일반적인 개발자들에게 전통적인 코드보다 가독성이 떨어지며 성능 또한 떨어지는 것을 확인 할 수 있었다!
문제를 풀어보면서 성능에 대한 궁금증이 생겼고 결과를 직접 확인 했지만 성능 차이의 원인에 대해서는 알아 보지 못한 아쉬움이 있었고, 그 원인에 대해 공부하여 조만간 정리해야겠다!