알고리즘

Comparable, Comparator를 이용한 정렬

고유빙글 2021. 12. 4. 06:56

Comparable , Comparator

 : 우선 둘 모두 인터페이스이다.
     즉, 둘 모두 인터페이스 내에 선언된 메소드를 반드시 구현해야 한다.
   
 : Comparable
     compareTo(T o) 메소드 하나가 선언되어 있다.

 : Comparator
     여러 메소드가 있지만 실질적으로는, compare(T o1,T o2)를 구현해야한다.

 : 추가로 Comparator에 여러 메소드가 있지만, 하나만 구현해도 되는 이유는
     Java8부터 interface에 일반 메소드를 구현할 수 있도록 변경되었다. default나 static으로 선언된 메소드는 일반 메소드로 구현할 수 있다.
     물론 default나 static으로 선언되지 않았어도 상위 타입에서 정의된 메소드가 있는경우 구현이 강제되지 않는다.

 : 이러한 compareTo 혹은 compare 메소드는 어떤 때 사용하면 좋을까
     기본적으로 자바에서 제공하는 primitive type은 부등호등으로 쉽게 비교가 가능하지만,
     새로운 클래스 객체를 만들어 비교하게 된다면 좀 다른 기능의 비교메소드가 있어야 편리하다.


 : 여기에는 복잡한 부분이 없어서 코딩으로 보여드리겠다.
     중간에 사용된 익명객체에대해 잘 모른다면 
     https://the-bingle.tistory.com/76 이 포스트를 보고 오시거나 구글에 익명객체를 검색해보시는 것을 추천한다.
     이 내용은 기본적인 두 인터페이스의 활용이다. 

     Java의 일반적인 정렬기준은 오름차순이 기준이 된다.
     compare, compareTo 에서 보았듯,
     두 값의 비교를 할때, 1과 3을 비교한다면 1 - 3으로 -2음수가 나올 것이다.
     즉, 오름차순 베이스일때는 compare, compareTo를 사용하여 비교할 경우 음수가 나오면 두 원소의 위치를 바꾸지 않는다.
     당연히 반대의 경우에는 원소의 위치를 바꾼다.

     두 수의 비교 결과에 따른 작동방식을 지정할 수 있게된다.
     1. 음수일 경우 : 두 원소의 위치를 교환안함
     2. 양수일 경우 : 두 원소의 위치를 교환

     정렬을 구현해보면 Counting Sort 같은 특수한 경우를 제외하고 

     Insertion, Quick, Merge 등 다양한 정렬 알고리즘은 
     '두 데이터(요소)의 비교'를 통해 두 원소를 교환할지 말지를 정하게 된다고 한다.
     ( 아직 위 정렬중에 구현해본것이 없다.. 배울게 넘나 많구만 )

 

     간단한 Arrays.sort()를 이용해서 정렬하는 코드를 짜보았다.

     이 전까지는 Arrays.sort()에서 지원하는 타입들만 정렬이 가능한지 알았는데,

     좀 실용적으로 활용하는 방법을 배웠다.

import java.util.Arrays;
import java.util.Comparator;

public class SortTest {
	
	public static void main(String[] args) {
		
		MInt[] arr = new MInt[10];
		
		for (int i = 0; i < arr.length; i++) {
			arr[i] = new MInt((int)(Math.random()*100));
		}
		
		System.out.print("정렬 전  : ");
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i].value + " ");
		}
		System.out.println();
		
		Arrays.sort(arr);
		
		System.out.print("정렬 후 : ");
		for (int i = 0; i < arr.length; i++) {
			System.out.print(arr[i].value + " ");
		}
		System.out.println();
		
		System.out.println("======================");
		
		YInt[] arr2 = new YInt[10];
		
		for (int i = 0; i < arr2.length; i++) {
			arr2[i] = new YInt((int)(Math.random()*100));
		}
		
		System.out.print("정렬 전 : ");
		for (int i = 0; i < arr2.length; i++) {
			System.out.print(arr2[i].value+" ");
		}
		System.out.println();
		
//		Arrays.sort(arr2);
//		
//		System.out.print("정렬 후 : ");
//		for (int i = 0; i < arr2.length; i++) {
//			System.out.print(arr2[i].value+" ");
//		}
//		System.out.println();
		
		// Arrays.sort() 메소드가 compareTo를 이용해 정렬하기 때문에 compare을 사용하는 클래스는 정렬할 수 없다.
		// compare을 이용해서 정렬하려면 추가적인 코딩이 필요하다.
		
		Arrays.sort(arr2, comp);
		
		System.out.print("정렬 후 : ");
		for (int i = 0; i < arr2.length; i++) {
			System.out.print(arr2[i].value+" ");
		}
		System.out.println();
		
	}
	
	
	static class MInt implements Comparable<MInt>{
		
		int value;
		
		public MInt(int value) {
			this.value = value;
		}
		
		@Override
		public int compareTo(MInt m) {
			return this.value - m.value;
		}
		
	}
	
	static Comparator<YInt> comp = new Comparator<YInt>() {
		
		@Override
		public int compare(YInt y1, YInt y2) {
			return y1.value - y2.value;
		}
	};
	
	static class YInt {
		
		int value;
		
		public YInt(int value) {
			this.value = value;
		}
		
	}
}

 

     이로써 내가 만든 클래스도 정렬을 손쉽게 할 수 있을것이다.