티스토리 뷰

대부분의 프로그래밍 언어에서 기본적으로 제공하는 sort 함수를 사용하면 일반적인 숫자나 문자열이 들어있는 배열을 정렬하는 것은 쉽다.

 

하지만 여러 속성이 들어있는 '객체' 들이 들어있는 배열이 있다면 어떻게 정렬할까? 예를 들어서 '학생' 클래스에는 학번, 이름, 전화번호, 성적이라는 속성들이 들어있는데 이 학생들을 성적순으로 정렬해야 한다면?

 

파이썬에서는 lambda 표현식이라는 걸 사용하면 dict를 값 기준으로 정렬한다던지 하는 것이 가능했었다.

 

res = sorted(genres_plays.items(), key=(lambda x: x[1]), reverse = True)

자바에서도 비슷한 일을 해야 할 일이 생겼다. '기록' 이라는 클래스가 있다. '기록' 클래스의 속성으로는 제목, 레벨, 난이도, 정확도, 점수, 날짜가 있다. 이 '기록' 들을 레벨 순으로, 정확도 순으로, 날짜 순으로 정렬하고 싶다. 자바에선 어떻게 할까?

 

1) Comparable 인터페이스를 클래스에 구현

public class EZ2Record implements Comparable<EZ2Record>{
    private String title;
    private String level;
    
    // ...

    public int compareTo(EZ2Record record){
        int lv_a = Integer.parseInt(this.level);
        int lv_b = Integer.parseInt(record.level);
        if (lv_a < lv_b)
            return 1;
        else if (lv_a == lv_b)
            return 0;
        else
            return -1;
    }

정렬하고 싶은 클래스에 'implements Comparable<ClassName>' 을 붙인 다음 'compareTo()' 라는 메서드를 오버라이드해준다. compareTo() 메서드의 인자로는 객체가 들어오는데, 이 메서드의 역할은 compareTo() 를 호출한 객체 (this) 와 인자로 들어온 객체를 가지고 안에서 "뭔가" 를 비교한 다음 1, 0, 또는 -1을 리턴하는 것이다(정확히는 양수냐 음수냐에 따라 동작이 달라지는 거지만 보통 1, 0, -1을 쓴다).

 

compareTo() 를 호출한다고 썼지만 직접적으로 개발자가 이걸 호출하는게 아니라, Comparable 인터페이스가 구현된 클래스 객체들이 담겨있는 배열을 sort하게 되면 자동으로 각 객체들에 대해서 이 메서드가 호출되면서 각각의 객체들끼리 비교를 수행하게 된다.

 

1이 리턴되면 두 객체의 자리가 바뀌며, 0이나 -1일 경우엔 바뀌지 않는다. '현재 객체의 값 > 인자로 들어온 객체의 값' 일 때 1을 리턴시키면 오름차순 정렬이 되며, -1을 리턴시키면 내림차순 정렬이 된다. 또는 리턴값은 그대로 두고 부등호만 반대로 바꿔도 오름차순/내림차순이 바뀐다.

 

클래스에 저걸 구현했으면 실제로 정렬하는 방법은, 배열이냐 ArrayList냐에 따라 다음과 같이 하면 된다. 위와 같이 compareTo() 메서드를 만들었다면 기록들이 레벨 순 (내림차순) 으로 정렬될 것이다.

 

Arrays.sort(records); // records가 배열일 경우
Collections.sort(records); // records가 ArrayList일 경우

2) Comparator 사용하기

 

1번 방법에서, compareTo() 메서드는 한 클래스에 하나밖에 있을 수 없기 때문에 정렬 기준도 하나밖에 될 수 없다. 만약 레벨 말고 다른 정렬 기준도 선택할 수 있게 하고 싶다면 어떻게 해야할까?

 

Collections.sort(records, new Comparator<EZ2Record>() {
	@Override
	public int compare(EZ2Record o1, EZ2Record o2) {
		float a = Float.parseFloat(o1.getRate().replace("%", ""));
		float b = Float.parseFloat(o2.getRate().replace("%", ""));
		if (a>b)
			return -1;
		else if (a==b)
			return 0;
		else
			return 1;
	}
});

Collections.sort() 는 1번 방법에서와 같이 하나의 인자만 받을 수도 있지만, 2번째 인자를 추가로 받을 수도 있다. 이 2번째 인자로 Comparator라는 인터페이스가 들어갈 수 있으며, 이 안에다가 compare() 메서드를 오버라이드해주면 된다.

 

compare() 메서드를 작성하는 방법은 compareTo() 와 유사하지만 여기선 비교할 클래스 안에 메서드를 정의한게 아니므로 this랑 파라미터를 비교하는게 아니라 파라미터를 두 개 (o1, o2) 받아서 서로 비교하게 된다.

 

정렬 기준을 선택하는 변수를 만든 다음 그 변수값에 따라 서로 다른 Collections.sort() 가 실행되도록 만들어주면 여러 기준으로 정렬할 수 있다.

공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
링크
TAG
more
«   2024/04   »
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30
글 보관함