프로그래밍/JAVA

[Java] 객체 비교와 정렬 기준

연유뿌린빙수 2024. 5. 3. 02:16

Java에서는 객체의 정렬을 위해 기본적으로 Comparable 인터페이스와 Comparator 인터페이를 제공한다.

 

Arrays.sort나 Collections.sort 등의 정렬 메서드는 이 두 인터페이스를 기반으로 작동한다. 단일 기준 뿐만 아니라 다중 조건 정렬이 필요할 때에는 직접 비교 기준을 정의할 수 있기에 다중조건 정렬에 자주 사용된다.

 

 

 

1. Comparable Interface 사용하기

Comparable은 객체 자체가 기본 정렬 기준을 가지도록 정의하는 인터페이스다.

즉, 해당 클래스의 인스턴스가 정렬 가능한 형태로 동작하게 한다.

class Student implements Comparable<Student> {
	int socre;
    int extra;
    
    @Override
    public int compareTo(Student other) {
    	// score를 기준으로
        if (this.score != other.score) {
        	returun this.score - other.score;
        }
        // 그다음인 extra를 기준으로
        else {
        	return this.extra - other.extra;
        }
    }
}

 

compareTo() 메서드는 현재 객체(this)와 비교 대상(other)의 순서를 결정한다.

 

음수 (< 0) this < other this가 앞에 옴
0 this == other 순서 동일
양수 (> 0) this > other this가 뒤로 감

 

 

  • 기본적으로 this - other오름차순 정렬을 의미한다
    예를 들어, this.score = 80, other.score = 90일 때, 80 - 90 = -10 → 음수 → this가 앞에 온다.
  • 내림차순 정렬을 원한다면 반대로 계산해주면 된다

 

 

 

즉 결과를 계산했는데 음수면 this가 앞으로 가는 것이고, 양수면 this가 뒤로간다.

 

오름차순 return this.x - other.x; “this가 작으면 앞으로!”
내림차순 return other.x - this.x; “this가 크면 앞으로!”

 

간단하게 정리하면 위와 같다.

 

 

 

Arrays.sort(studentList);

그래서 위와 같은 Comparable을 구현한 클래스는 위처럼 정렬할 수 있다.

위에서 설정한대로라면 오름차순 정렬이고, 만약 내림차순으로 하고 싶다면 클래스 내에서 설정해도 되고,

다음과 같이 작성해도 된다.

Arrays.sort(studentList, Collections.reversOrder());

 

 

 

 

 

2. Comparator를 이용한 외부 비교 정의

 

Comparator클래스 외부에서 정렬 기준을 정의하고 싶을 때 사용한다.
객체를 직접 수정할 수 없거나 여러 기준으로 다양한 정렬을 수행해야 할 때 유용하다.

Arrays.sort(studentList, new Comparator<int[]>) {
	@Override
    public int compare(int[] a, int[] b) {
    	if (a[1] != b[1]) {
        	return b[1] - a[1]; // 1차 기준 : 내림차순
        }
        if (a[2] != b[2]) {
        	return b[2] - a[2]; // 2차 기준 : 내림차순
        }
        return a[0] - b[0]; // 3차 기준 : 오름차순
    }
}

 

이 방식은 익명 클래스로 Comparator를 바로 구현한 예시이다.
여기서도 compare() 메서드의 반환 규칙은 Comparable과 동일하다.

 

 

람다식을 통한 표현도 가능하다.

 

익명 클래스를 람다식으로 단순화할 수도 있다.
람다식을 사용하면 코드가 훨씬 간결해지고, 가독성도 높아진다.

Arrays.sort(projects, (a, b) -> {
    if (a[1] != b[1]) return b[1] - a[1];
    if (a[2] != b[2]) return b[2] - a[2];
    return a[0] - b[0];
});

 

람다식에서는 매개변수 타입을 생략할 수 있으며,
간단한 비교 로직을 명확하게 표현할 수 있다.

 

 

 

 

COS PRO 1급 - Java 기출 문제

 

- Comparable

class Team implements Comparable<Team> {
	int projectScore;
	int implScore;
	int teamNo;
	
	Team(int projectScore, int implScore, int teamNo) {
		this.projectScore = projectScore;
		this.implScore = implScore;
		this.teamNo = teamNo;
	}
	
	// 비교 기준
	@Override
	public int compareTo(Team other) {
		// 1차 기준 : projectScore
		if (this.projectScore != other.projectScore) {
			return other.projectScore - this.projectScore;
		}
		else {
			// 2차 기준 : implScore
			if (this.implScore != other.implScore) {
				return other.implScore - this.implScore;
			}
			else {
				return this.teamNo - other.teamNo;
			}
		}
	}
}

class Solution {

	public static int[] solution(int[][] projects) {
		
		Team[] teamList = new Team[projects.length];
		int[] seq = new int[projects.length]; // 발표 순
		for (int i = 0; i < projects.length; i++) {
			int[] temp = projects[i];
			Team tempTeam = new Team(temp[1], temp[2], temp[0]);
			teamList[i] = tempTeam;
		}
		
		Arrays.sort(teamList);
		for (int i = 0; i < teamList.length; i++) {
			seq[i] = teamList[i].teamNo;
		}
		return seq;
	}
}

 

- Comparator

class Solution {
    public int[] solution(int[][] projects) {
        Arrays.sort(projects, new Comparator<int[]>() {
            @Override
            public int compare(int[] a, int[] b) {
                if(a[1] != b[1]) return b[1] - a[1];
                if(a[2] != b[2]) return b[2] - a[2];
                return a[0] - b[0];
            }
        });
        
        int[] answer = new int[projects.length];
        for(int i = 0; i < projects.length; i++) 
            answer[i] = projects[i][0];
        return answer;
    }
}

 

 

 

COS PRO 1급 - Java 기출 문제

 

- Comparable

class Family implements Comparable<Family> {
	int id;
	int hasChild;
	int childNo;
	int score;
	
	public Family(int id, int hasChild, int childNo, int score) {
		this.id = id;
		this.hasChild = hasChild;
		this.childNo = childNo;
		this.score = score;
	}
	
	@Override
	public int compareTo(Family other) {
		
		// 자녀 유무
		if (this.hasChild == other.hasChild) {
			// 자녀의 수로
			if (this.childNo != other.childNo) {
				return this.childNo - other.childNo;
			} else {
				return this.score - other.score;
			}
		} else {
			return this.hasChild - other.hasChild;
		}
	}
}

class Solution {

	public static int[] solution(int[][] household) {
		int[] answer = new int[household.length];
		Family[] families = new Family[household.length];
		for (int i = 0; i < household.length; i++) {
			Family fam = new Family(
					household[i][0], household[i][1], household[i][2], household[i][3]);
			families[i] = fam;
		}
		
		Arrays.sort(families, Collections.reverseOrder());
		for (int i = 0; i < household.length; i++) {
			Family tempFam = families[i];
			answer[i] = tempFam.id;
		}
		return answer;
	}
}

 

- Comparator

import java.util.*;

class Solution {
    public int[] solution(int[][] household) {
        Arrays.sort(household, new Comparator<int[]>() {
            @Override
            public int compare(int[] a, int[] b) {
                if(a[1] != b[1]) return b[1] - a[1];
                if(a[2] != b[2]) return b[2] - a[2];
                if(a[3] != b[3]) return b[3] - a[3];
                return a[0] - b[0];
            }
        });
        
        int[] answer = new int[household.length];
        for(int i = 0; i < household.length; i++) 
            answer[i] = household[i][0];
        return answer;
    }
}