본문 바로가기
프로그래밍 언어

[Java] Comparable과 Comparator의 차이

by 내기록 2022. 8. 10.
반응형

 

아래 블로그 내용에서 다시 보고싶은 내용만 추렸습니다.

더 자세히 알고싶으신 분은 아래 링크로 가는걸 추천드립니다.

 

자바 [JAVA] - Comparable 과 Comparator의 이해

아마 이 글을 찾아 오신 분들 대개는 Comparable과 Comparator의 차이가 무엇인지 모르거나 궁금해서 찾아오셨을 것이다. 사실 알고보면 두 개는 그렇게 어렵지 않으나 아무래도 자바를 학습하면서 객

st-lab.tistory.com

 

Comparable vs Comparator

 

Comparable은 "자기 자신과 매개변수 객체를 비교" 한다.

compareTo(T o)

 

Comparator는 "두 매개변수 객체를 비교" 한다.

Compare(T o1, T o2)

 

Comparable은 자기 자신과 파라미터로 들어오는 객체를 비교하는 것이고, Comparator는 파라미터로 들어오는 두 객체를 비교하는 것이다. 즉, 본직적으로 비교하는 것 자체는 같지만, 비교 대상이 다르다는 것이다.

 

또 다른 차이점은 Comparable은 lang 패키지에 있기 때문에 import를 해줄 필요가 없지만, Comparator는 util 패키지에 있다.

 

- Comparable

자기 자신과 매개변수 객체를 비교한다.

 

https://docs.oracle.com/javase/8/docs/api/java/lang/Comparable.html#method.summary

public class ClassName implements Comparable<Type> { 
 
	// 필수 구현 부분
	@Override
	public int compareTo(Type o) {
		/*
		 비교 구현
		 */
	}
}

 

Example)

class Student implements Comparable<Student> {
 
	int age;
	int class;
	
	Student(int age, int classNumber) {
		this.age = age;
		this.classNumber = classNumber;
	}
	
	@Override
	public int compareTo(Student o) {
    
		// 자기자신의 age가 o의 age보다 크다면 양수
		if(this.age > o.age) {
			return 1;
		}
		// 자기 자신의 age와 o의 age가 같다면 0
		else if(this.age == o.age) {
			return 0;
		}
		// 자기 자신의 age가 o의 age보다 작다면 음수
		else {
			return -1;
		}
	}
}

compareTo 메소드는 int 값을 반환해야 하는데, "자기 자신을 기준으로 상대방과 얼마나 차이가 나느냐" 를 기준으로 반환한다.

꼭 1, -1 로 반환하지 않고 양수, 음수로 반환해도 되지만 추천하지 않는다.

두 수의 차를 리턴하는 방법도 있다. 하지만 이 방법을 잘못 사용하면 Underflow(범위의 하한선을 넘어버리는 것) 또는 Overflow(범위의 상한선을 넘어버리는 것) 이 발생할 수 있어 위 코드처럼 < , > , = 로 대소 비교를 하는 것이 일반적이다.

 

 

 

- Comparator

두 매개변수 객체를 비교한다.

 

 

 

import java.util.Comparator;	// import 필요
public class ClassName implements Comparator<Type> { 
 
	// 필수 구현 부분
	@Override
	public int compare(Type o1, Type o2) {
		/*
		 비교 구현
		 */
	}
}

 

Example)

import java.util.Comparator;	// import 필요
class Student implements Comparator<Student> {
 
	int age;
	int class;
	
	Student(int age, int classNumber) {
		this.age = age;
		this.classNumber = classNumber;
	}
	
	@Override
	public int compare(Student o1, Student o2) {
    
		// o1의 학급이 o2의 학급보다 크다면 양수
		if(o1.classNumber > o2.classNumber) {
			return 1;
		}
		// o1의 학급이 o2의 학급과 같다면 0
		else if(o1.classNumber == o2.classNumber) {
			return 0;
		}
		// o1의 학급이 o2의 학급보다 작다면 음수
		else {
			return -1;
		}
	}
}

매개변수로 들어오는 두 객체 o1, o2를 비교한다.

a.compare 메소드에서 a와 비교하고 싶다면 아래와 같이 하면 된다.

a.compare(a,b);

 

 

 

Comparator 기능만 따로 두고싶을 때는 익명 객체(클래스)를 활용한다.

익명 객체는 '이름이 정의되지 않은 객체' 를 의미하며

위와 같이 특정 구현 부분만 따로 사용하거나, 부분적으로 기능을 일시적으로 바꾸고 싶을 때 사용한다.

 

import java.util.Comparator;
 
public class Test {
	public static void main(String[] args) {
    
		// 익명 객체 구현 1
		Comparator<Student> comp1 = new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				return o1.classNumber - o2.classNumber;
			}
		};
	}
 
	// 익명 객체 구현 2
	public static Comparator<Student> comp2 = new Comparator<Student>() {
		@Override
		public int compare(Student o1, Student o2) {
			return o1.classNumber - o2.classNumber;
		}
	};
}
 
 
// 외부에서 익명 객체로 Comparator가 생성되기 때문에 클래스에서 Comparator을 구현 할 필요가 없다.
class Student {
 
	int age;
	int class;
	
	Student(int age, int classNumber) {
		this.age = age;
		this.classNumber = classNumber;
	}
 
}

위 코드를 보면 외부에서 Comparator를 구현하는 익명객체가 생성되었기 때문에 Student 클래스 내부에서 Comparator를 구현할 필요가 없어졌다.

 

Example)

import java.util.Comparator;
 
public class Test {
	public static void main(String[] args)  {
 
		Student a = new Student(17, 2);	// 17살 2반
		Student b = new Student(18, 1);	// 18살 1반
		Student c = new Student(15, 3);	// 15살 3반
			
		// comp 익명객체를 통해 b와 c객체를 비교한다.
		int res = comp.compare(b, c);
		
		if(res > 0) {
			System.out.println("b객체가 c객체보다 크다.");
		}
		else if(res == 0) {
			System.out.println("두 객체의 크기가 같다.");
		}
		else {
			System.out.println("b객체가 c객체보다 작다.");
		}
		
	}
	
	public static Comparator<Student> comp = new Comparator<Student>() {
		@Override
		public int compare(Student o1, Student o2) {
			return o1.classNumber - o2.classNumber;
		}
	};
}
 
class Student {
      ...
}

익명 객체는 이름이 정의되지 않은 하나의 새로운 클래스와 같다.

익명 객체를 가리키는 변수명만 달리하면 몇 개든 자유롭게 생성할 수 있다.

 

 

 

 

References

https://st-lab.tistory.com/243?category=830901 

반응형

댓글