[Java] Person 클래스 다양한 기준으로 정렬 해보기 (다양한 compareTo 정의해보기)

이준영·2023년 12월 6일
1

🟫 Java

목록 보기
14/21
post-thumbnail

보통 primitive 값을 정렬 할 경우, Object 클래스의 equals() 메소드를 따로 정의하지 않아도 비교가 가능하고, Comparable 인터페이스의 compareTo() 메소드를 구현하지 않아도 Arrays.sort() 메소드를 통해 오름차순 정렬이 쉽게 가능합니다.
그러나 대부분의 문제는 인스턴스를 비교하고 정렬할 때 발생합니다.

❗️ 정수 대신 인스턴스를 비교, 정렬 할 경우 ❗️

인스턴스는 정렬하는데 기준이 필요하기 때문에

정렬할 인스턴스의 클래스에 Comparable 인터페이스를 구현 해주고 해당 인터페이스의 메소드인 compareTo() 메소드를 원하는 정렬 기준으로 오버라이딩 해주어야 합니다.

compareTo(Object o)
return 값
- 양수 (비교한 두 수 위치 변경)
- 음수 (위치 변경 x)
- 0 (위치 변경 X)
예시
@Override
public int compareTo(Object o) { // 나이의 오름차순 정렬
	Person p = (Person) o;
	return this.age - p.age;
}

비교의 경우는 정렬할 때 구현한 compareTo() 메소드를 기준으로 return 값이 0 일 경우 해당 인덱스를 반환해 줍니다.


간단한 Person 클래스 입맛대로 비교, 정렬하기

Person 클래스

class Person implements Comparable {

	private String name;
	private int age;

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
    }
}

나이 오름차순 정렬

class Person implements Comparable {

	private String name;
	private int age;

	public Person(String name, int age) {
		this.name = name;
		this.age = age;
    }
    
    @Override
	public int compareTo(Object o) { // 나이의 오름차순 정렬
		Person p = (Person) o;
		return this.age - p.age;
	}
}

정렬 후 이진 탐색
public static void main(String[] args) {

	Person[] ar = new Person[10];

    ar[0] = new Person("Lee", 29);
    ar[1] = new Person("Lee", 29);
    ar[2] = new Person("Soo", 37);
    ar[3] = new Person("So", 36);
    ar[4] = new Person("So", 99);
    ar[5] = new Person("So", 23);
    ar[6] = new Person("Abc", 37);
    ar[7] = new Person("aBC", 38);
    ar[8] = new Person("asdfg", 17);
    ar[9] = new Person("sssssss", 47);

	// 정렬
    Arrays.sort(ar); 

	// 정렬된 배열 출력	
    for (Person p : ar) { 
        System.out.println(p); 
    }
    // 탐색 결과 출력
	System.out.println();
    System.out.println("idx: " + Arrays.binarySearch(ar, new Person("NULL", 29))); 
}

[출력 결과]:
asdfg: 17
So: 23
Lee: 29
Lee: 29
So: 36
Soo: 37
Abc: 37
aBC: 38
sssssss: 47
So: 99

idx: 2
❗️이름이 다르더라도 나이만 같다면 이진 탐색의 결과로 인덱스가 반환됩니다.
(나이만 같아도 compareTo()의 return 값이 0이되기 때문에 인스터스를 찾았다고 판단)


이름 길이순 + 알파벳 순 정렬, 이름이 같다면 나이 오름차순 정렬

static class Person implements Comparable {

    .
    .
    .
    
    @Override
    public int compareTo(Object o) { 
        Person p = (Person) o;
        // 이름 길이 오름차순 정렬
        if (this.name.length() > p.name.length()) {
            return 1;
        } else if (this.name.length() < p.name.length()) {
            return -1;
		// 이름길이가 같다면 
        } else {
            for (int i = 0; i < this.name.length(); i++) {
                if ((int) this.name.toLowerCase().charAt(i) != (int) p.name.toLowerCase()
                        .charAt(i)) {
                    // 알파벳순 정렬
                    return (int) this.name.toLowerCase().charAt(i) - (int) p.name.toLowerCase()
                    		.charAt(i);
                }
            }
            // 이름이 같다면 나이순 정렬
            return this.age - p.age;
        }

    }
정렬 후 이진 탐색
public static void main(String[] args) {

	Person[] ar = new Person[10];

    ar[0] = new Person("Lee", 29);
    ar[1] = new Person("Lee", 29);
    ar[2] = new Person("Soo", 37);
    ar[3] = new Person("So", 36);
    ar[4] = new Person("So", 99);
    ar[5] = new Person("So", 23);
    ar[6] = new Person("Abc", 37);
    ar[7] = new Person("aBC", 38);
    ar[8] = new Person("asdfg", 17);
    ar[9] = new Person("sssssss", 47);

	// 정렬
    Arrays.sort(ar); 

	// 정렬된 배열 출력	
    for (Person p : ar) { 
        System.out.println(p); 
    }
    // 탐색 결과 출력
	System.out.println();
    System.out.println("idx: " + Arrays.binarySearch(ar, new Person("NULL", 99)));
        System.out.println("idx: " + Arrays.binarySearch(ar, new Person("So", 99)));
}

[출력 결과]:
So: 23
So: 36
So: 99
Abc: 37
aBC: 38
Lee: 29
Lee: 29
Soo: 37
asdfg: 17
sssssss: 47

idx: -9 // 탐색에 실패하여 음수 반환
idx: 2
❗️ 이름이 일치하고, 나이까지 같아야 compareTo() 가 0을 반환하기에 둘 다 일치해야 해당 인덱스를 반환합니다.


코테문제 풀 때마다 이차원 배열 정렬이나, 선언한 클래스를 정렬해야할 때 애를 많이 먹었었기에 한번 이것 저것 해보며 정리 해 봄.
profile
작은 걸음이라도 꾸준히

0개의 댓글