카테고리 없음

[Java] Collection.sort, comperator, Map의 정렬

키보드발 2022. 9. 13. 03:43
//value 오름차순
//value가 같을때 key 오름차순

	List<Integer> list = new ArrayList<>(res.keySet());
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                int cmp = Double.compare(res.get(o1), res.get(o2));
                return cmp == 0 ? o1-o2 : cmp;
            }
        });

Collection.sort를 알기위한 배경지식을 공부했다.

먼저 Collections는 컬렌션을 위한 메소드를 제공한다.

Collection.sort( 대상, 기준 )을 넣는다.

기준은 기본값 오름차순이다.

o1과 o2 를 비교해서

if(o1 > o2) return  1      9 8 7 6 5 4 3 2 1 (서로 위치바꿈, 바꾸는 식을 사용하기위해 1=true인듯) 

if(o1 < o2) return -1      1 2 3 4 5 6 7 8 9 ( 기본이 오름차순이기 때문에 바꾸는식을 사용 안하기위해 -1=false인듯)

if(o1 = o2) return  0      

(두 값이 같은 경우일때, 또 다른 기준을 적용하기 위해 존재하는 것 같음, 예를 들어 map을 value순으로 정렬하되 같을 경우 key를 내림차순으로 정렬해라 같은 기준을 말하는것

예를 들어 Map의 key:1 value :10, key:3 value:10으로 정렬되있을 때 key : 3 key: 1순으로 정렬하기위해  0이라는 기준이 필요함)

 

collection의 map의 기준

Map또한 기본이 오름차순인것 같음

value는 기본이 오름차순이고

Map의 value가 같다면 key를 오름차순으로 정렬함

if( key1 > key2) return  1 이기때문에 서로 위치를 바꾸는 식이 사용함

if( key1 < key2) return -1 이기때문에 서로 위치를 바꾸는 식이 사용되지 않음

if(key = key) =0 서로 같을때 새로운 기준을 정하기 위해 존재함

Map

key : 5, value 8

key : 3, value 5

key : 1, value 8

key : 2, value 4

의 Map을 value로 오름차순으로 정렬한다면

key : 2, value 4

key : 3, value 5

로 정렬되다가

key : 1, value 8 == key : 5, value 8  value가 같기때문에0이고

0일때 

if( key1 > key2) return  1 이기때문에 서로 위치를 바꾸는 식이 사용함

if( key1 < key2) return -1 이기때문에 서로 위치를 바꾸는 식이 사용되지 않음

if(key = key) =0 서로 같을때 새로운 기준을 정하기 위해 존재함

의 규칙이 적용되어 key도 오름차순으로 정렬됨

 

따라서 이런 식으로 정렬할 수 있음

        //value를 내림차순
        //value가 같을때 key를 오름차순
        List<Integer> list = new ArrayList<>(res.keySet());
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
            	//위에서 말했듯 기본값이 오름차순임
                //return으로 1이나오면 res.get(o1)과 res.get(o2)를 서로 바꾸는거임 res.get(o1) res.get(o2)였다면 o2 o1으로
                //o1 < o2일때만 서로의 위치를 바꾸는 식을 적용시켜주지않겠다는것(버블정렬을 사용하는듯)
                
                //Double.compare(res.get(o1), res.get(o2))을 했을때
                //res.get(o1) < res.get(o2)이라면 -1의 값이나옴 따라서 서로의 위치를 바꾸는 식이 적용안됨
                //즉 res.get(o1) < res.get(o2)가 아니면 위치바꾸겠다는것 오름차순만 인정하겠다는것
                
                //내림차순을 하고 싶다면?
                //Double.compare(res.get(o1), res.get(o2))을 했을때
                //res.get(o2) > res.get(o1)일때 1임, 이 값을 -1로 만들어주는거임
                //즉 res.get(o2) > res.get(o1)일때만 서로의 위치를 바꾸는 식을 적용시키지 않겠다는것
                int cmp = Double.compare(res.get(o1), res.get(o2))*(-1);
            	
                
                //value의 값이 같을때 기준을 만드는 것임 res.get(o1) == res.get(o1)이라면
                //바꾸는 식을 어떻게 적용할까를 만들어 줄 수 있음
                //아무것도 적지 않으면 o1 < o2 일때 -1로 처리하는 것같음
                //반복하지만 당연히 o1 > o2 일때는 = 1, o1 = o2 일때는 0 (여기서 map의 key라 당연히 0일 수가 없겠지만..key는 중복될 수 없으니까)
                //따라서 여기서 key는 Integer니까 빼서 조건을 알려주는거임, 밑의 강의 처럼 삼항연산자로처리해도
                상관없음 중요한건 결과적으로 1,-1,0 어떤게 나가는가임
                //우리가 원하는건 key의 오름차순임
                //즉 o1 < o2여야 한다는것,
                
                //key1=1, key2=2이며
                //value(key1) = value(key2)이고
                
                //Map에
                //비교하는 순간 [key1=1, value] ,[key2 = 2, value]  순서로 저장되어있다면 위치를 안바꾸겠다는 것임
                //즉 저 순서인 상태에서 안 바꾸고 싶다 -> 바꾸는 식을 쓰기 싫다 -> -1을 내놔라임
                //그렇다면 key가 오름차순으로 하기위해서는? keys = {1,2,3,4,5,6,7} 같이 되어야한다는것
                //key1 < key2이면 바꾸지말라는것 
                // A < B인 경우는? A-B인경우, Integer.compare(o1,o2) = -1인 경우이다.
                //(참고:compare에서 -3,-4로 나가도 상관없는것 같다. 중요한것 양수냐 음수냐 0이냐다.
                //어처피 밖에서 compare>0, compare<0, compare==0의 조건으로 처리되는것 같다.)
   				//즉 return이 의미하는것은
                //비교했는데 0이야? 같아? 그러면 key끼리 비교해봐
                //key1 < key2인 상태야? 오케이, 바꾸는 식 쓰지마 -1가지고 나가
                //key > key2인 상태야? 안돼, 바꾸는 식 써 1가지고 나가
                //인 뜻인거다.
   
            	return cmp == 0 ? Integer.compare(o1,o2) : cmp;
            }
        });

 

이러한 기본 개념을 알았다면 이제는 여러가지 방법을 구현할 수가 있다.

 

//value 내림차순
//value가 같을때 key 오름차순

	List<Integer> list = new ArrayList<>(res.keySet());
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                int cmp = Double.compare(res.get(o2), res.get(o1));
                //int cmp = Double.compare(res.get(o1), res.get(o2))*(-1);
              	//cmp = res.get(o2) - res.get(o1) //로 해도 되지만 오버플로우가 발생하면 오류나니 주의
                
                return cmp == 0 ? Integer.compare(o1,o2) : cmp;
                //return cmp == 0 ? Integer.compare(o1,o2) : cmp;
                //return cmp == 0 ? o1-o2 : cmp;
            }
        });
----------------------------------------------------------------------------------
//value 내림차순
//value가 같을때 key 내림차순

	List<Integer> list = new ArrayList<>(res.keySet());
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                int cmp = Double.compare(res.get(o2), res.get(o1));
                //int cmp = Double.compare(res.get(o1), res.get(o2))*(-1);
                //cmp = res.get(o2) - res.get(o1) //로 해도 되지만 오버플로우가 발생하면 오류나니 주의
                
                return cmp == 0 ? Integer.compare(o2,o1) : cmp;
                //return cmp == 0 ? Integer.compare(o1,o2)*(-1) : cmp;
                //return cmp == 0 ? o2-o1 : cmp; //오버플로우나면 오류나니 주의 o1 > o2일때 음수
            }
        });
----------------------------------------------------------------------------------
//value 오름차순
//value가 같을때 key 오름차순
//기본값이 value가 같을때 key는 오름차순이기때문에
//굳이 return cmp == 0 ? Integer.compare(o1,o2) : cmp; 을 쓸필요는 없음
//return Double.compare(res.get(o1), res.get(o2));만 해줘도 충분함

	List<Integer> list = new ArrayList<>(res.keySet());
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                int cmp = Double.compare(res.get(o1), res.get(o2));
                //cmp = res.get(o1) - res.get(o2) //로 해도 되지만 오버플로우가 발생하면 오류나니 주의
                
                return cmp == 0 ? Integer.compare(o1,o2) : cmp;
                //return cmp == 0 ? o1-o2 : cmp; //오버플로우나면 오류나니 주의
            }
        });
-----------------------------------------------------------------------------------
//value 오름차순
//value가 같을때 key 내림차순

	List<Integer> list = new ArrayList<>(res.keySet());
        Collections.sort(list, new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                int cmp = Double.compare(res.get(o1), res.get(o2));
                //cmp = res.get(o1) - res.get(o2) //로 해도 되지만 오버플로우가 발생하면 오류나니 주의
                
                return cmp == 0 ? Integer.compare(o1,o2)*(-1) : cmp;
                //return cmp == 0 ? Integer.compare(o2,o1) : cmp;
                //return cmp == 0 ? o2-o1 : cmp; //오버플로우나면 오류나니 주의 o1 > o2일때 음수
            }
        });


 즉 중요한건 compare에서 나가는게 음수냐 양수냐임

o1은 now라 생각하고 o2 next라고 생각하면 이해가 쉬워짐

 

현재 1이고 다음이 2다

나는 오름차순을 만들고 싶어

그렇다면 지금 이 순서를 유지해야겠지, 순서를 유지한다? -> 위치를 변경시키지않는다-> 음수를 내보낸다.

나는 내림차순을 만들고싶어

그렇다면 지금 순서를 바꿔야겠지, 순서를 바꾼다-> 위치를 변경시킨다->양수를 내보낸다.

https://lookingfor.tistory.com/entry/%EC%9E%90%EB%B0%94-%EB%AC%B8%EC%9E%90%EC%97%B4-%EB%B9%84%EA%B5%90-%ED%95%A8%EC%88%98-compare-compareTo

 

자바 문자열 비교 함수 compare(), compareTo()

compareTo() : 문자열의 사전순 값을 비교하여 그에 해당되는 int 값을 리턴한다. 예로 A > B 라고 가정하면, - A = A = 0 (동일한 경우) - A > B = 1 (좌측 값이 큰 경우) - B > A = -1 (좌측 값이 작은 경우) 예..

lookingfor.tistory.com

https://st-lab.tistory.com/243

//왜 o1-o2를 하면 오버플로우가 날 수 있으니 주의해야하는지 써있음

 

자바 [JAVA] - Comparable 과 Comparator의 이해

아마 이 글을 찾아 오신 분들 대개는 Comparable과 Comparator의 차이가 무엇인지 모르거나 궁금해서 찾아오셨을 것이다. 사실 알고보면 두 개는 그렇게 어렵지 않으나 아무래도 자바를 학습하면서 객

st-lab.tistory.com

 

https://loosie.tistory.com/429

 

[프로그래머스] 2019 카카오 블라인드 #2 실패율 (Java)

#2 실패율 난이도 : LEVEL 1 유형 : 자료구조 코딩테스트 연습 - 실패율 실패율 슈퍼 게임 개발자 오렐리는 큰 고민에 빠졌다. 그녀가 만든 프랜즈 오천성이 대성공을 거뒀지만, 요즘 신규 사용자의

loosie.tistory.com

https://cornswrold.tistory.com/114

 

[JAVA] Map에 있는 데이터를 Value기준으로 정렬하기

Map의 Value데이터 기준으로 정렬하기 TreeSet을 이용하면 Key 기준으로 쉽게 정렬할 수 있으나, Value로 정렬해주는 컬렉션은 존재하지 않는다. Value로 map을 정렬을 하려면 Comparator 인터페이스를 이용

cornswrold.tistory.com

https://www.youtube.com/watch?v=EW3Mub24wYg 

https://www.youtube.com/watch?v=u0pJGFyvrqc