JAVA에서 배열을 정렬을 하는 방법은 여러가지가 있다.
먼저 기본 자료형인 int, double, String 등의 배열은
Arrays.sort() 메서드를 호출하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
|
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
int[] intArray = {5, 2, 1, 4, 3};
// 1, 2, 3, 4, 5로 정렬 된다.
}
}
|
동적배열인 List는
Collections.sort() 메서드를 호출하면 된다.
1
2
3
4
5
6
7
8
9
10
11
12
13
|
import java.util.*;
public class Example {
public static void main(String[] args) {
// 1, 2, 3, 4, 5로 정렬된다.
}
}
|
Arrays.sort()는 파라미터로 T [] 인 기본 배열을 받고
Collections.sort()는 파라미터로 List<T> 인 List를 받는다.
그렇다면 sort() 메서드에서 기본 자료형들은 어떻게 비교해서 정렬을 할 수 있을까.
바로 Comparable 인터페이스를 구현했기 때문이다.
1
2
3
4
|
interface Comparable<T> {
int compareTo(T obj)
}
|
즉, Comparable 인터페이스의 구현해서 compareTo 메서드를 오버라이딩한 클래스는
sort() 메서드를 통해 비교가 가능한 것이다.
그렇다면 임의로 만든 클래스의 객체 배열은 어떻게 정렬할까
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
|
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
Person[] people = {new Person(30, "홍길동"), new Person(20, "김철수"), new Person(25, "김영희")};
// 정렬 실패.
}
}
class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
|
위의 같은 코드를 실행한다면
Exception in thread "main" java.lang.ClassCastException: Person cannot be cast to java.lang.Comparable
라는 오류가 발생한다.
Person 클래스는 java lang.Comparable에 캐스팅 될 수 없다는 오류이다.
한마디로 Person 클래스는 Comparable 인터페이스를 구현하지 않았기 때문에
에러가 난 것이고 Arrays.sort() 메서드로 정렬을 할 수 없는 것이다.
Person 클래스에 Comparable 인터페이스를 구현하고 compareTo메서드를 오버라이딩하면
Arrays.sort() 메서드로 정렬을 할 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
Person[] people = {new Person(30, "홍길동"), new Person(20, "김철수"), new Person(25, "김영희")};
// 나이 순 정렬 성공 {20, 김철수}, {25, 김영희}, {30, 홍길동}으로 정렬된다.
}
}
class Person implements Comparable<Person>{
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
/*
* 나이를 기준으로 정렬하고 나이가 같다면 이름 순으로 정렬한다.
*/
@Override
public int compareTo(Person other) {
if (r == 0) {
}
return r;
}
}
|
하지만 이렇게 Comparable 인터페이스를 구현한 클래스라면
compareTo 메서드를 여러개 재정의 할 수 없으니
비교기준을 한가지 밖에 가질 수 없다.
위의 코드처럼 나이를 기준으로 먼저 비교해서 정렬하고
나이가 같다면 이름 순으로 정렬하는 compareTo 메서드를 재정의했다면
이름 순으로 먼저 비교하고 싶을 때는 난감한 경우가 생긴다.
그럴 땐 Comparator 인터페이스를 구현하면 된다.
1
2
3
4
|
interface Comparator<T> {
int compare(T obj1, T obj2);
}
|
Comparator 인터페이스는 Comparable 인터페이스와 다르게
compare 메서드를 오버라이딩 해야한다.
compare 메서드는 compareTo 메서드와 다르게 파라미터 변수가 두 개이다.
compareTo 메서드는 파라미터 한개로 객체를 받아서
this 키워드를 사용해서 비교했지만
compare 메서드는 파라미터 두개로 두개의 객체를 받아서
서로 비교해주면 된다.
Comparator 인터페이스는 비교 기준이 여러 개 일때 사용하는 인터페이스기에
비교할 클래스에 구현하는 것이 아니라
따로 클래스를 구현해서 만들어 주는 것이 좋다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
|
import java.util.Arrays;
import java.util.Comparator;
public class Example {
public static void main(String[] args) {
Person[] people = {new Person(30, "홍길동"), new Person(20, "김철수"), new Person(25, "김영희")};
// {20, 김철수}, {25, 김영희}, {30, 홍길동}으로 정렬된다.
// {25, 김영희}, {20, 김철수}, {30, 홍길동}으로 정렬된다.
}
}
class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
class PersonAgeComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
if (r == 0) {
}
return r;
}
}
class PersonNameComparator implements Comparator<Person> {
@Override
public int compare(Person p1, Person p2) {
if (r == 0) {
}
return r;
}
}
|
두 Person 객체가 동일한 경우에만 compare 메소드가 0을 리턴해야 하는 것이 바람직하기 때문에,
PersonAgeComparator 클래스에서는 나이 기준 Comparator이지만 name까지 비교를 하고
PersonNameComparator 클래스에서는 이름 기준 Comparator이지만 age까지 비교를 한다.
정렬을 한 번하고 Comparator 클래스들을 재 사용할 것이 아니라면
굳이 class를 만들 필요 없이 무명 클래스와 람다 익스프레션을 활용하면 된다.
이 방법들이 코드 양이 훨씬 줄어든다.
1
2
3
4
5
6
7
8
9
|
public class Person {
int age;
String name;
public Person(int age, String name) {
this.age = age;
this.name = name;
}
}
|
무명 클래스를 활용한 예시
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
|
import java.util.Arrays;
import java.util.Comparator;
public class Example {
public static void main(String[] args) {
Person[] people = {new Person(30, "홍길동"), new Person(20, "김철수"), new Person(25, "김영희")};
@Override
public int compare(Person p1, Person p2) {
if (r == 0) {
}
return r;
}
}); // 나이 기준 정렬
// {20, 김철수}, {25, 김영희}, {30, 홍길동}으로 정렬된다.
@Override
public int compare(Person p1, Person p2) {
if (r == 0) {
}
return r;
}
}); // 이름 기준 정렬
// {25, 김영희}, {20, 김철수}, {30, 홍길동}으로 정렬된다.
}
}
|
람다 익스프레션을 활용하면 코드를 더 줄일 수 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
|
import java.util.Arrays;
import java.util.Comparator;
public class Example {
public static void main(String[] args) {
Person[] people = {new Person(30, "홍길동"), new Person(20, "김철수"), new Person(25, "김영희")};
if (r == 0) {
}
return r;
});
// 나이 기준 정렬
// {20, 김철수}, {25, 김영희}, {30, 홍길동}으로 정렬된다.
if (r == 0) {
}
return r;
});
// 이름 기준 정렬
// {25, 김영희}, {20, 김철수}, {30, 홍길동}으로 정렬된다.
}
}
|
Stream API를 활용하는 방법도 있다.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
|
import java.util.Arrays;
public class Example {
public static void main(String[] args) {
Person[] people = {new Person(30, "홍길동"), new Person(20, "김철수"), new Person(25, "김영희")};
people = Arrays.stream(people)
.sorted((p1, p2) -> {
if (r == 0) {
}
return r;
})
.toArray(Person[]::new);
// 나이 기준 정렬
// {20, 김철수}, {25, 김영희}, {30, 홍길동}으로 정렬된다.
people = Arrays.stream(people)
.sorted((p1, p2) -> {
if (r == 0) {
}
return r;
})
.toArray(Person[]::new);
// 이름 기준 정렬
// {25, 김영희}, {20, 김철수}, {30, 홍길동}으로 정렬된다.
}
}
|
'Java' 카테고리의 다른 글
함수형 인터페이스 API 정리 (0) | 2020.02.12 |
---|---|
추상 클래스와 인터페이스 (0) | 2020.02.10 |
StringBuilder, StringBuffer, System.out.print, append (1) | 2019.07.11 |
2차원 배열의 깊은 복사, 임의의 클래스 복사 (0) | 2019.06.13 |
비트 연산자 & 쉬프트 연산자 (0) | 2019.05.27 |