Comparable 인터페이스를 구현해, 사용자 정의 클래스 정렬하기

hyekyeong Song·2020년 7월 9일
0

Java에서 배열의 정렬을 수행할 때 Arrays.sort()메소드를 사용하며, ArrayList를 정렬할 때에는 Collections.sort()메소드를 사용한다. 그러나 이러한 기본타입의 정렬 이외에 사용자 정의 클래스를 특정 기준(변수)에 따라 정렬해야하는 경우가 매우 많은데 이는 Comparable 인터페이스를 구현하여 수행할 수 있다.

참고 예제

예제를 바탕으로 설명할 예정인데, 참고한 예제는 '프로그래머스'의 '튜플'(2019 카카오 개발자 겨울 인턴십) 문제이다.

이 문제를 풀때, 원소의 숫자가 몇번 나타났는지 카운팅하여 이를 바탕으로 풀었는데 간단히 예를 들자면

주어진 입력 문자열 : "{{1,2,3},{2,1},{1,2,4,3},{2}}"
에 대해 숫자 1은 3번 나타났고, 숫자 2는 4번, 숫자 3은 2번, 숫자 4는 1번 나타났다.
따라서 정답 튜플은 카운팅 개수를 기준으로 내림차순하여 구할 수 있고, 즉 [2, 1, 3, 4] 가 된다

따라서 원소의 숫자와 해당 원소가 몇 번 나타났는지 저장할 수 있는 사용자 정의 객체가 필요했다.

1) 사용자 정의 객체

그렇게 구현한 사용자 정의 객체는 다음과 같다.

    public class ElementData implements Comparable<ElementData> {
        int num;    //원소의 숫자
        int cnt;    //원소의 숫자가 몇 번 나타났는지 카운팅해 저장

        public ElementData(int num, int cnt) {
            this.num = num;
            this.cnt = cnt;
        }

        @Override
        public int compareTo(ElementData elementData) { //내림차순 정렬
            if(this.cnt < elementData.cnt) {
                return 1;
            } else {
                return -1;
            }
        }
    }

주 목적은 원소의 숫자가 몇 번 나타났는지 카운팅한 값(변수 cnt)을 기준으로 내림차순 하는 것이기 때문에 Comparable클래스를 implements하여 compareTo() 메소드를 오버라이딩했다.

compareTo() 메소드는 양수, 0, 음수를 리턴할 수 있는데 리턴하는 값에 따라 정렬이 달라진다.

  • 양수(1) 리턴 : 파라미터로 들어온 객체와 원래(this) 객체의 자리를 바꾼다
  • 음수(-1), 0 리턴 : 자리를 변경하지 않는다.

현재 목적은 cnt값을 기준으로 내림차순 정렬하는 것이기 때문에, elementData.cnt의 값이 this.cnt보다 더 크면 둘의 자리를 바꾸도록 1를 리턴했다.

2) 사용자 정의 객체의 정렬

위에서 정의한 사용자 정의 객체(ElementData)를 실제로 정렬하는 코드는 다음과 같다. (정렬과 관계없는 불필요한 코드들은 생략함)

    public int[] solution(String s) {
    
        //불필요한 코드 생략
        
        ElementData[] cntArr = new ElementData[100002];
        
        for(int i=0; i<100002; i++) {   //cnt 0으로 초기화
            cntArr[i] = new ElementData(i, 0);
        }

        //불필요한 코드 생략
        
        for(int i=0; i<s.length(); i++) { //숫자로 변환해서 카운팅하기
            if(s.charAt(i) >= '0' && s.charAt(i) <= '9') {  //숫자이면
                if(tempNum == 0) {  //첫번째로 시작하는 숫자이면
   		 //불필요한 코드 생략

            } else if(s.charAt(i) == ',' || s.charAt(i) == '}') {
                if(tempNum != 0) { //원소 만들어서 카운팅하고 tempNum초기화
    		    //불필요한 코드 생략
                
                    cntArr[tempNum].cnt += 1;
                    
    		    //불필요한 코드 생략
                }
            }
        }

        //카운팅 된 숫자로 내림차순 정렬하기
        Arrays.sort(cntArr);

        //불필요한 코드 생략
    }

참고) compareTo()메소드의 return

위에서 자리 바꿈에 대해서만 return을 언급했는데, 문자열 비교를 통해 compareTo()메소드에 대해 더 정확히 알아보자!

<compareTo()를 사용한 문자열 비교를 통해 return값 이해하기>

compareTo()메소드는 오름차순이 기본이다. 따라서 String은 사전순(ex. a > b > c)을 기준으로 비교한다.

String str1 = "a", String = str2 = "b" 

두 문자열 변수가 있다고 하자.

  • Case 1 : return -1
str1.compareTo(str2);

는 -1을 리턴한다. 파라미터 문자열(str2)이 기준 문자열(str1)보다 사전순으로 뒤에 있기 때문이다.

  • Case 2 : return 1
str2.compareTo(str1);

는 1을 리턴한다. 파라미터 문자열(str1)이 기준 문자열(str2)보다 사전순으로 앞에 위치하기 때문이다.

  • Case 3: return 0
str1.compareTo("a");

는 0을 리턴한다. 파라미터 문자열("a")과 기준 문자열(str1)이 같은 값을 가지기 때문(정확히 말하면 같은 객체를 참조하기 때문)이다.

profile
안녕하세요😀😀

0개의 댓글