java/Comparable

남순식·2022년 12월 12일
1
post-thumbnail

Comparable <

comparable 은 인터페이스며
지금까지 정렬을 위해 사용한다고 생각했다.
반쪽짜리 정답을 외운 채
알고리즘 프로그래밍 문제를 풀이하다 벽에 부딪혔다.

comparable 은
객체끼리 비교 할 수 있도록 한다.
정확히는
주체가되는 것은 자기자신객체며 매개변수로 들어오는 객체와의 비교를 한다.

이해를 위해
조금은 조잡한 예제를 만들어봤다.

public class ComparableDemo {

    static class Car {

        String name; 
        int hp; //최대 마력
        Car () {}

        Car (String name, int hp) {
            this.hp = hp;
            this.name = name;
        }
}

이러한 클래스로 객체 5개 를 생성하고 List에 추가하여 최대마력을 가지고 오름차순으로 정렬하려고한다.

List<Car> carList = new ArrayList<>();
        
carList.add(new Car("car1",800));
carList.add(new Car("car2",500));
carList.add(new Car("car3",200));
carList.add(new Car("car4",150));
carList.add(new Car("car5",400));

현재는list에 추가 된 데이터 순서로 정렬 돼있을것이다.
이것을 원하는 모양으로 정렬하기위해서 어떻게 해야할까?

먼저 데이터가 Integer형식이라면 sort 함수를 활용하여 쉽게 정렬할 수 있다.

int a = 1;
int b = 2;

이같은 경우라면 a < b 라는 것은 java가 알 수 있다는 말이다.

하지만 지금 리스트에 추가된 데이터형식은
내가 만든 Car클래스형식이다
때문에 리스트에 추가된 객체는 사용자가 지정해주지 않는 한 대소관계를 알 수 없다.

이때 사용하는것이 comparable 이다.

interface Comparable<T> {...}
라고 되어있다.
<>사이에있는 T는 비교 할 객체 타입을 의미한다.
Car와 Car의 비교를 하고 싶었으니 <Car>로 사용 하면 되겠다.
따라서 이렇게 사용하면 된다.

class Car implements Comparable<Car> {

    String name;
    int hp; //최대 마력
    Car () {}

    Car (String name, int hp) {
        this.hp = hp;
        this.name = name;
    }


    @Override
    public int compareTo(Car o) {
        .
        .
        .
    }
}

Comparable은 interface 이기때문에
compareTo라는 메서드를 완성시켜야한다.

@Override
public int compareTo(Car o) {
	  //자신의 hp보다 매개변수 hp가 더큰경우 음수
      if (this.hp < o.hp){
    	  return -1;
      }
      //자신과 매개변수의 hp가 같은경우 0
      else if (this.hp == o.hp) 
	  {
		  return 0;
      }
      //자신의 hp가 매개변수의 hp보다 큰경우 양수
      else 
	  {
		  return 1;
	  }
}

compareTo는 int를 반환하게 돼있다.
기준이 무엇일까
생각해보자 자신과 매개변수의 hp비교이다.
나자신이 매개변수 hp와의 값을 비교하여 대소관계를 파악해야한다.

나의 hp = 20이고
비교할 매개변수의 hp = 40 일때
나는 메개변수hp보다 -20만큼 작다는 뜻이다.
앞에 양수 음수 0 표현도 이때문이다.

실행이 잘 되는지 살펴보자

public static void main(String[] args) {

        Car car1 = new Car("myCar", 20);
        Car car2 = new Car("yourCar", 40);

        if (car1.compareTo(car2) < 0){
            System.out.println(car1.name + "가 " + car2.name + "보다 작습니다");
        } else if (car1.compareTo(car2) == 0){
            System.out.println(car1.name + "가 " + car2.name + "와 같습니다.");
        } else {
            System.out.println(car1.name + "가 " + car2.name + "보다 큽니다.");
        }
  }

(자신)car1.compareTo((매개변수)car2);
실행해본 결과 대소관계를 확인 할 수 있었다.

자신과 매개변수의 hp의 값을 가지고 비교하였고,
값 차이를 가지고 양수,음수,또는 0 을 반환한다고 하였다.
그렇다면 더 간결하게 표현할 수 있을것이다.

public class ComparableDemo 
    static class Car implements Comparable<Car> {

        String name;
        int hp; //최대 마력
        Car () {}

        Car (String name, int hp) {
            this.hp = hp;
            this.name = name;
        }

        @Override
        public int compareTo(Car o) {

            return this.hp - o.hp;
        }
    }
}

이렇게 하면 자신보다 매개변수가 클때 음수, 같을때 0, 작을때 양수가 반환될 것이다.
이로서 비교는 끝이났다.

이것을 가지고 오름차순을 정렬 할 수 있겠다.

public static void main(String[] args) {

        List<Car> arrayList = new ArrayList<>();

        arrayList.add(new Car("car1",800));
        arrayList.add(new Car("car2",500));
        arrayList.add(new Car("car3",200));
        arrayList.add(new Car("car4",150));
        arrayList.add(new Car("car5",400));


        System.out.println("==정렬 전==");
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.println(arrayList.get(i).name + ":" + arrayList.get(i).hp + " ");
        }

        System.out.println();

        System.out.println("==정렬 후==");
        Collections.sort(arrayList);
        for (int i = 0; i < arrayList.size(); i++) {
            System.out.println(arrayList.get(i).name + ":" + arrayList.get(i).hp + " ");
        }
}

compareTo 메서드는
자기자신과 매개변수로 들어온 객체를 비교하는 것이기 때문에
반환값이 양수면 자기자신이 큰것이고,
음수면 매개변수가 더큰것이며,
0이면 크기가 같다는 뜻이 되겠다.

이와 반대로

public static void main(String[] args) {

      Car car1 = new Car("myCar", 20);
      Car car2 = new Car("yourCar", 40);

      if (car1.compareTo(car2) < 0){
          System.out.println(car1.name + "가 " + car2.name + "보다 작습니다");
      } else if (car1.compareTo(car2) == 0){
          System.out.println(car1.name + "가 " + car2.name + "와 같습니다.");
      } else {
          System.out.println(car1.name + "가 " + car2.name + "보다 큽니다.");
      }
}

여기서

		public int compareTo(Car o) {

            return o.hp - this.hp;
		}

이렇게 반환한다고하면

40 - 20 이 되고
자기자신hp가 더 작은값임에도
불구하고 양수가 나오기때문에
내림차순 정렬이 된다.

profile
java 주니어

0개의 댓글