Comparable과 Comparator를 이용한 Class Sort

Posted by 열정보이
2019. 3. 31. 21:13 JAVA

 

오늘은 Comparable과 Comparator를 이용한 정렬에 대해 알아보겠습니다.

 

우리는 평소에 Arrays 클래스의 sort() 메서드나 Collections 클래스의 sort() 메서드를 사용합니다.

sort하는 인스턴스의 타입이 무엇이냐에 따라 Arrays를 사용할지 Collections를 사용할지 결정하죠.

 

 public class Test {
	public static void main(String[] args) {
		int i = 10;
		int[] arr1 = new int[10];
		ArrayList<Integer> arr2 = new ArrayList<>();
		
		for (int j = 0; j < arr1.length; j++) {
			arr1[j] = i - j;
			arr2.add(i-j);
		}
		
		Arrays.sort(arr1);
		Collections.sort(arr2);
		
		for (int j = 0; j < arr1.length; j++) {
			System.out.println(arr1[j] + " " + arr2.get(j));
		}
	}
 }

위와 같이 List 타입일 경우 Collections.sort를 사용하고, 일반 클래스일 경우 Arrays.sort를 사용합니다.

 

그렇다면, Class에 대한 정렬은 어떻게 할까요?

예를 들어 Student 라는 Class가 있고, 학생의 '이름순서' 대로 정렬을 하고 싶습니다.

이때 사용하는게 Comparable interface 입니다.

바로 확인해보죠.

 

 import java.util.Arrays;
 import java.util.Scanner;

 public class Test {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		Student[] students = new Student[3];

		for (int i = 0; i < students.length; i++) {
			String name = scan.next();
			int num     = scan.nextInt();
			students[i] = new Student(name, num);
		}
		
		Arrays.sort(students);
		for(Student s : students) {
			System.out.println(s.name + " " + s.number);
		}
		
	}
	/* Student Class */
	static class Student implements Comparable<Student>{
		String name;
		int number;
		
		public Student(String name, int num) {
			this.number = num;
			this.name   = name;
		}
		
		/* CompareTo를 Override하여 sort 방법을 명시한다. */
		@Override
		public int compareTo(Student o) {
			return - this.name.compareTo(o.name);
		}
	}

 }

 

Student Class는 Comparable interface를 구현합니다. 이때, compareTo 메서드를 Override하여 sort의 기준을 정해줍니다.

 

this.name 은 현재 클래스의 name 값이고, 파라미터로 넘어온 Student 인스턴스의 name과 비교하여 sort의 기준을 잡아줍니다.

이때, return 값이 음수냐 양수냐에 따라 오름차순과 내림차순을 결정하게 됩니다.

String 클래스가 제공하는 compareTo 메서드 같은 경우 비교하는 String이 같을경우 0, 비교하는 String이 작을 경우 - 를 그리고 클 경우 + 값을 반환합니다.

 

일반적으로 return this.name.compareTo(o.name); 과 같이 반환한다면, Student 클래스를 담은 배열을 정렬하면 오름차순으로 정렬하게 됩니다. 이때 앞에 - 를 붙여주면 부호가 변경되기 때문에 내림차순으로 정렬을 하게 할 수 있습니다.

 

 홍길동 1
 김바보 2
 장독대 3
 홍길동 1
 장독대 3
 김바보 2

그렇기 때문에 '홍길동 1, 김바보 2, 장독대 3' 을 입력할 경우 String을 내림차순으로 정렬하여 위와 같은 결과를 출력하게 됩니다.(위에 3줄은 입력이며, 아래 3줄이 출력입니다.)

 

이렇게 클래스에 Comparable interface를 구현하여 Sort의 기준을 잡아줄 수 있습니다.

하지만 이럴 경우 Student Class의 Sort 기준은 항상 이름순이 됩니다.

저희는 좀 더 동적인 정렬을 원하는 상황이 된거죠. 즉, 어떤 상황에서는 이름순으로, 어떤 상황에서는 숫자로 정렬을 하고 싶습니다.

 

그럴 경우 Comparator interface를 이용합니다.

바로 보도록 하죠.

 

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

 public class Test {
	public static void main(String[] args) {
		Scanner scan = new Scanner(System.in);
		Student[] students = new Student[5];
		
		/* 숫자로 정렬 기준을 잡은 Comparator이며 오름차순. */
		Comparator<Student> numSort = new Comparator<Student>() {
			@Override
			public int compare(Student o1, Student o2) {
				return o1.number - o2.number;
			}
		};
		
		/* 이름으로 정렬 기준을 잡은 Comparator이며 오름차순. */
		Comparator<Student> nameSort = new Comparator<Student>() {

			@Override
			public int compare(Student o1, Student o2) {
				return o1.name.compareTo(o2.name);
			}
		};
		
		for (int i = 0; i < students.length; i++) {
			String name = scan.next();
			int num     = scan.nextInt();
			students[i] = new Student(name, num);
		}
		System.out.println("#숫자로 정렬#");
		Arrays.sort(students,numSort);
		for(Student s : students) {
			System.out.println(s.name + " " + s.number);
		}
		
		System.out.println("\n#이름으로 정렬#");
		Arrays.sort(students,nameSort);
		for(Student s : students) {
			System.out.println(s.name + " " + s.number);
		}
		
	}
	/* Student Class */
	static class Student {
		String name;
		int number;
		
		public Student(String name, int num) {
			this.number = num;
			this.name   = name;
		}
	}

 }

Comparator를 Student 타입으로 구현을 하며, 이때 숫자로 정렬하는 numSort와 이름으로 정렬하는 nameSort로 각각 만들어 줍니다.

 

그리고 Arrays에 기준값을 넣어주면 되죠.

출력은 다음과 같습니다.

 김길동 99
 강감찬 1
 니달리 50
 완득이 20
 도도한 70
 #숫자로 정렬#
 강감찬 1
 완득이 20
 니달리 50
 도도한 70
 김길동 99

 #이름으로 정렬#
 강감찬 1
 김길동 99
 니달리 50
 도도한 70
 완득이 20
 

위에 5라인은 입력에 대한 값이고 아래 값들은 출력입니다.

이쁘게 정렬되었네요.

 

이렇게 Comparator와 Comparable를 이용해 Class 정렬을 해보았습니다.

그럼 이만~

'JAVA' 카테고리의 다른 글

JAVA Call By Reference? Value?  (0) 2019.03.03