[자바] Comparator vs Comparable

Romy·2023년 11월 24일

📌 Comparator/Comparable란 ?

Comparator/Comparable 둘 다 정렬할 때, 비교의 기준을 정해주기 위해 사용하는 인터페이스 입니다. 단순히 원소를 1:1로 비교할 수 있지만, 특별히 객체들 간의 비교를 가능하게 해주는 것이 특징 입니다.

예시를 들어볼까요 ? 키와 몸무게를 담은 사람이라는 클래스가 있다고 가정해봅시다.

class Person {
	String 이름;
	int;
	int 몸무게;

	public Person(String 이름, int, int 몸무게) {
				this.이름 = 이름;
				this.=;
				this.몸무게 = 몸무게;
	}
}

그리고 두 사람을 새로 생성 해줍니다.

Person p1 = new Person("철수", 175, 65);
Person p2 = new Person("준하", 170, 70);

우리는 키를 기준으로, 혹은 몸무게를 기준으로 비교할 수 있습니다. 어떤 기준으로 비교를 할지 정해줘야할 때, Comparable과 Comparator 를 사용합니다.

그렇다면, 두 인터페이스의 차이점은 무엇일까요 ? 우선 간단하게 말씀드리도록 하겠습니다.

  • Comparator vs Comparable
    • Comparable : 자기 자신과 다른 객체 비교, compareTo() 오버라이딩
    • Comparator : 다른 두 객체를 비교, compare() 오버라이딩

참고로, 두 인터페이스는 인터페이스 내에 선언된 comepareTo() 와 cmpare() 메서드를 반드시 구현해주어야 합니다. 참고로, 두 메소드 모두 int 값을 반환하는데, 비교하는 두 객체 비교 기준을 서로 빼주면 됩니다.

제대로 설명이 들어가기 전, compareTo()와 compare() 반환 값에서 한번 알아둘 필요가 있습니다.

@Override
public int compareTo(Node o) {
    return 0;
}
@Override
public int compare(Object o1, Object o2) {
    return 0;
}

두 함수 모두 int가 반환값인 것을 알 수 있습니다. 정확히는 음수, 0, 양수 3가지로 구분하여 판단합니다. Java에서 정렬할 때 기본 값이 ‘오름차순’ 입니다. 오른차순이라는 것은, 자기 자신보다 뒤에 있는 원소가 더 크다는 것을 의미하죠. 앞에 원소에서 뒤 원소를 빼면 어떻게 될까요? 바로 음수가 나옵니다. 그렇기 때문에, 음수가 나오면 오름차순이 되고 양수가 나오면 자기 자신 객체 혹은 앞 객체가 더 크다는 것을 의미하기 때문에 내림차순으로 됩니다.

다시 정리하자면 기본 정렬이 오름차순이기 때문에 음수가 기본입니다. 그래서 내림차순으로 하기 위해서는 양수값을 반환해주기 위해 뒷 원소에서 앞 원소를 빼주면 됩니다.

  • Comparator & Comparable
    • 양수일때 위치교환!
      • o1 - o2 → 올림차순
      • o2 - o1 → 내림차순

그렇다면, 이제 구체적으로 한번 볼까요?

📌 Comparable

  • 정의 : 정렬 수행 시, 기본적으로 적용되는 정렬 기준이 되는 메서드를 정의해 놓는 인터페이스
  • 패키지 : java.lang.Comparable

Comparable 과 같은 경우는 정렬 기준을 “미리” 정의 해두어, 정렬시 Comparable의 구현 내용에 맞게 정렬이 수행됩니다. Integer, Double 등의 경우 비 내림차순, String 클래스의 경우 사전순으로 정렬되게 구현됩니다.

사용방법

아까 만들어준 Person 클래스를 가져와보도록 하겠습니다. 그리고 Comparable 인터페이스를 상속받아줍니다. 상속받을 때, 식별자는 사용하는 클래스명을 넣어주면 됩니다. 우선, 키를 기준으로 비교해보도록 하겠습니다.

class Person implements Comparator<Person> {
	String 이름;
	int;
	int 몸무게;

	public Person(String 이름, int, int 몸무게) {
				this.이름 = 이름;
				this.=;
				this.몸무게 = 몸무게;
	}

	@Override
  public int compareTo(Person p) {
      return this.- p.;
			//return Integer.compare(this.키, p.키); //다른 방법
  }
}

이렇게 Comparable 인터페이스를 상속받고, compareTo()에 해당 클래스 변수 중 기준 삼을 것을 가져와주면 됩니다. 자기자신 객체 - 비교하는 객체로 return을 하면, 오름차순으로 정렬이 됩니다. 내림차순으로 정렬을 하고 싶으면 비교하는 객체 - 자기 자신 객체 로 해주시면 됩니다.실제로 사용할 땐, 아래와 같이 사용할 수 있습니다.

class Person implements Comparator<Person> {
	String 이름;
	int;
	int 몸무게;

	public Person(String 이름, int, int 몸무게) {
				this.이름 = 이름;
				this.=;
				this.몸무게 = 몸무게;
	}

	@Override
  public int compareTo(Person p) {
      return this.- p.;
  }
}

public class Main {
    public static void main(String[] args) {
        Person p1 = new Person("철수", 175, 65);
        Person p2 = new Person("준하", 170, 70);
				ArrayList<Person> people = new ArrayList<>();

        Collection.sort(people);

				for(Person person : people) {
					System.out.println(person.name);
				}
    }
}

결과를 보면 키가 작은 준하가 먼저 나오는 것을 볼 수 있습니다.

📌 Comparator

  • 패키지 : java.util.Comparator

Comparator은 기본 정렬 기준과 다른 새로운 정렬 기준을 세워야할 떄 사용이 됩니다. 주로, 익명 클래스로 사용되며 Arrays.sort() 혹은 Collections.sort() 내부에 정렬 기준으로 구현하면 됩니다.

사용방법(1) - 익명클래스

//Arrays.sort() 에 사용하는 예시
Arrays.sort(arrs, new Comparator<Person>(){ //익명클래스 사용, 제너릭스 주의
	@Override
	public int compare(Person p1, Person p2) {
		// TODO Auto-generated method stub
		return 0;
	}
})

//사람의 키를 기준으로 올림차순
Collections.sort(list, new Comparator<Person>() {
    @Override
    public int compare(Person p1, Person p2) {
        return p1.- p2.;
    }
});

//사람의 키를 기준으로 내림차순
Collections.sort(list, new Comparator<String>() {
    @Override
    public int compare(Person p1, Person p2) {
        return p2.- p1.;
    }
});

Comparator를 상속받아 클래스를 만들지만, 클래스의 이름이 정의되어 있지 않는 익명 클래스임을 알 수 있습니다. 정석대로 하면, CustomComparator와 같이 따로 클래스를 만들어줘야 하지만, 익명 클래스를 통해 간단하게 만들고 처리할 수 있게 되었습니다.

또한 Lambda 함수를 통해서 구현도 가능합니다.

사용방법(2) - 람다식

Collections.sort((p1, p2) -> {
        return p1.- p2.;
});

지금까지 Java 정렬 때 사용되는 Comparable 과 Comparator 에 대해서 알아봤습니다. 부족한 부분이 있거나 틀린 부분이 있다면 알려주시면 수정하도록 하겠습니다. 감사합니다 🙂

  • 참고자료
profile
👩‍💻 IT Engineering

0개의 댓글