Java

[Java]Comparable 인터페이스

DevStory 2022. 9. 8.

Comparable 인터페이스란?

java.lang 패키지에 존재하는 Comparable는 사용자가 정의한 클래스의 객체를 정렬하는 목적으로 사용되는 인터페이스입니다.

 

Comparable 인터페이스에는 compareTo()라는 단 하나의 메서드만 존재합니다. 인터페이스는 메서드의 이름, 반환 타입, 매개변수가 정의된 껍데기에 불과하므로 compareTo() 메서드를 사용하려면 특정 클래스에서 Comparable 인터페이스를 구현해야 합니다.

 

사용자가 정의한 클래스의 객체를 정렬하기 위해 Comparable 인터페이스를 구현하는 이유는 어떤 필드를 기준으로 값을 비교하여 정렬할 것인지 명시하기 위해서입니다.

 

예를 들어, Person 클래스의 객체로 구성된 List를 정렬하고자 합니다. 정렬 기준은 Name 필드가 될 수 있고 Age 필드가 될 수 있습니다.

public class Person {
  private String Name;
  private Integer Age;

  public Person(String name, Integer age) {
    Name = name;
    Age = age;
  }

  public String getName() {
    return Name;
  }

  public void setName(String name) {
    Name = name;
  }

  public Integer getAge() {
    return Age;
  }

  public void setAge(Integer age) {
    Age = age;
  }
}

만약, Name 필드 기준으로 정렬한다면, 대소문자를 구분할 것인지, 대소문자를 구분하지 않을 것인지 고민할 수 있습니다. 즉, 사용자가 정의한 클래스는 정렬 기준이 없으므로 개발자가 Comparable 인터페이스를 사용하여 정렬 기준을 구현해야 합니다.


Comparable 클래스의 compartTo 메서드

Comparable 클래스의 compareTo() 메서드를 구현하기 위해서는 다음 규칙을 따라야 합니다.

- 두 객체는 동일한 타입이어야 합니다.

- 현재 객체가 다른 객체보다 큰 경우 양의 정수를 반환합니다.

- 현재 객체와 다른 객체가 동일한 경우 0을 반환합니다.

- 현재 객체가 다른 객체보다 작은 경우 음의 정수를 반환합니다.

- Overflow, Underflow가 발생하지 않도록 양의 정수는 1, 음의 정수는 -1을 반환하는 것이 좋습니다.


Comparable 구현

다음 예제는 Person 클래스에서 Comparable 인터페이스를 구현합니다.

 

[구현 방법]

순서 1. implements 키워드를 사용하여 Comparable 인터페이스를 구현하며, 타입을 명시합니다.

순서 2. compareTo() 메서드를 재정의하며, 비교 기준을 설정하는 소스 코드를 구현합니다.

 

다음 예제는 Comparable 인터페이스가 구현된 Person 클래스입니다.

public class Person implements Comparable<Person> {
  private String Name;
  private Integer Age;

  public Person(String name, Integer age) {
    Name = name;
    Age = age;
  }

  @Override
  public int compareTo(Person o) {
    if(this.Age > o.Age) return 1;
    else if(this.Age == o.Age) return 0;
    else return -1;
  }
}

 

다음 예제는 main문에서 Person 클래스의 객체를 생성 후 compareTo() 메서드를 호출합니다.

public static void main(String args[]) {
  Person person1 = new Person("둘리", 10);
  Person person2 = new Person("또치", 10);

  System.out.println("person1.compareTo(person2): " + 
          person1.compareTo(person2));
}

[실행 결과]

person1.compareTo(person2): 0

Person 클래스의 compareTo() 메서드는 Age 필드의 값을 비교하므로 0이 반환되었습니다.


Comparable 인터페이스를 사용하여 정렬

위 예제에서 Comparable 인터페이스를 구현하고 compareTo() 메서드를 재정의한 다음 두 객체를 비교하는 방법을 보여줬습니다. 하지만, 단순히 두 객체를 비교하기 위해 Comparable 인터페이스를 구현하는 것보다 equals() 메서드를 재정의하는 것이 좋습니다.

 

Comparable 인터페이스를 사용하는 목적은 어디까지나 사용자가 정의한 클래스의 객체로 구성된 집합(배열, List, Stream 등..)을 정렬하는 경우입니다.

 

다음 예제는 Person 클래스에서 Comparable 인터페이스를 구현하고 Age 필드를 기준으로 두 객체를 비교하는 compareTo() 메서드를 재정의합니다. 그리고 main문에서 Collections 클래스의 sort() 메서드를 사용하여 Person 클래스의 객체로 구성된 ArrayList를 정렬합니다.

 

[Person 클래스]

public class Person implements Comparable<Person> {
  private String Name;
  private Integer Age;

  public Person(String name, Integer age) {
    Name = name;
    Age = age;
  }
  
  @Override
  public int compareTo(Person o) {
    if(this.Age > o.Age) return 1;
    else if(this.Age == o.Age) return 0;
    else return -1;
  }

  @Override
  public String toString() {
    return "Person{" +
            "Name='" + Name + '\'' +
            ", Age=" + Age +
            '}';
  }
}

[main문]

public static void main(String args[]) {
  ArrayList<Person> personArrayList = new ArrayList<>();
  personArrayList.add(new Person("둘리", 30));
  personArrayList.add(new Person("또치", 40));
  personArrayList.add(new Person("마이콜", 20));
  personArrayList.add(new Person("희동이", 5));

  System.out.println("[정렬 전]");
  for(Person person:personArrayList) {
    System.out.println(person.toString());
  }

  Collections.sort(personArrayList);

  System.out.println("\n[정렬 후]");
  for(Person person:personArrayList) {
    System.out.println(person.toString());
  }
}

[실행 결과]

[정렬 전]
Person{Name='둘리', Age=30}
Person{Name='또치', Age=40}
Person{Name='마이콜', Age=20}
Person{Name='희동이', Age=5}

[정렬 후]
Person{Name='희동이', Age=5}
Person{Name='마이콜', Age=20}
Person{Name='둘리', Age=30}
Person{Name='또치', Age=40}

Collections 클래스의 sort() 메서드 내부에서 Person 클래스의 compareTo() 메서드를 호출하여 ArrayList를 정렬합니다.

 

만약, Person 클래스가 Comparable 인터페이스를 구현하지 않는다면, Collections.sort() 메서드에서 컴파일 에러가 발생합니다.

여기서 핵심 내용은 Comparable 인터페이스를 구현하면, Collections 클래스의 sort() 메서드가 알아서 compareTo() 메서드를 호출한다는 것입니다.

반응형

댓글