Arrays.sort(arr); 은 배열 arr을 오름차순으로 정렬한다.
하지만 내림차순 정렬이 필요한 경우가 점차 많아졌고 방법을 정리할 겸 sort()와 관련된 내용을 다시 공부하기로 했다.
Arrays.sort(a) & Arrays.sort(a, fromIndex, toIndex)
Arrays (Java SE 17 & JDK 17)
public class Arrays extends Object This class contains various methods for manipulating arrays (such as sorting and searching). This class also contains a static factory that allows arrays to be viewed as lists. The methods in this class all throw a NullPo
docs.oracle.com
Arrays 클래스 문서에서 sort를 검색하면 아래와 같이 오버로딩된 메서드를 볼 수 있다.
sort를 클릭해 보면 아래와 같이 설명이 나와있다.
정렬 알고리듬으로 Dual-Pivot QuickSort를 활용하고 해당 알고리듬은 시간복잡도 O(n log(n))을 가진다고 한다.
해당 코드를 VS Code로 찾아보았다.
API 문서와 동일한 설명이 적혀있고 DualPivoitQuicksort 클래스의 sort 메서드를 호출하는 것을 확인할 수 있다.
추가로 더 들어가 봤는데, 아래는 DualPivotQuicksort 클래스의 sort 메서드이다.
static으로 선언이 되었기 때문에 참조변수 없이 활용이 가능하다.
Arrays 클래스에서 아래의 sort도 발견하였는데 위의 sort보다 매개변수가 2개 더 많다.
그래서 해당 메서드를 사용해 보았다.
0 ~ 9까지 순서 없이 담겨있는 배열을 생성하고 Arrays.sort 메서드를 호출했다. 아래는 출력 결과이다.
@param에 설명이 나와있듯 9번 index는 제외하고 3번 index ~ 8번 index만 정렬이 된 모습이다.
@throws를 확인해 보기 위해 fromIndex에 toIndex보다 더 큰 값을 담은 코드와 그 결과이다.
설명대로 나오는 것을 확인할 수 있었다.
parallelSort 메서드도 발견했는데 내용을 찾아보니 병렬로 배열을 정렬하는 메서드라고 한다.
Comparator & Comparable
이것저것 간단히 보았는데, 사실 정말 알고 있어야 할 것은 Comparator와 Comparable이다.
이 둘은 인터페이스로 각각 구현해야 하는 메서드를 가지고 있다.
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/util/Comparator.html
Comparator (Java SE 17 & JDK 17)
Type Parameters: T - the type of objects that may be compared by this comparator All Known Implementing Classes: Collator, RuleBasedCollator Functional Interface: This is a functional interface and can therefore be used as the assignment target for a lambd
docs.oracle.com
https://docs.oracle.com/en/java/javase/17/docs/api/java.base/java/lang/Comparable.html
Comparable (Java SE 17 & JDK 17)
Type Parameters: T - the type of objects that this object may be compared to All Known Subinterfaces: ArrayType, ByteValue, CharValue, ChronoLocalDate, ChronoLocalDateTime , Chronology, ChronoZonedDateTime , ClassType, Delayed, DoubleValue, Field, FloatVal
docs.oracle.com
Comparator
Comparator는 java.util에 정의되어 있는 인터페이스로 많은 메서드를 담고 있긴 하지만
대부분 static, default 메서드이다.
따라서 compare와 equals만 남는데, equals는 Object 클래스에 구현되어 있기에 compare만 구현하면 된다.
compare 메서드를 살펴보자.
int compare(T o1, T o2)로 선언되어 있고 o1과 o2의 비교 결과에 따라 양수, 0, 음수를 반환한다고 한다.
내용이 복잡하니 바로 활용해 보자.
import java.util.Comparator;
public class Sort{
public static void main(String[] args) {
Number n1 = new Number(1);
Number n2 = new Number(2);
System.out.println(n1.compare(n1, n2));
}
}
class Number implements Comparator<Number>{
int n;
Number(int n) {
this.n = n;
}
@Override
public int compare(Number o1, Number o2) {
return o1.n - o2.n;
}
}
Number 객체의 n에 대해 비교하는 코드이다.
인자로 받은 두 개의 객체를 서로 비교해 값을 반환한다. 결과는 -1이 나온다.
Comparable
Comparable는 java.lang에 구현된 인터페이스로 메서드를 하나만 가지고 있다. 즉, compareTo만 구현하면 된다.
실제로 확인해 보면 주석을 제외했을 때 Comparable.class의 코드는 아래가 전부이다.
package java.lang;
import java.util.*;
public interface Comparable<T> {
public int compareTo(T o);
}
Number를 이용해 Comparable을 사용해 보았다.
public class Sort{
public static void main(String[] args) {
Number n1 = new Number(1);
Number n2 = new Number(2);
System.out.println(n1.compareTo(n2));
}
}
class Number implements Comparable<Number>{
int n;
Number(int n) {
this.n = n;
}
@Override
public int compareTo(Number o) {
return this.n - o.n;
}
}
compare와 달리 인자로 하나의 객체를 받는다.
즉, 자기 자신과 인자로 받은 객체를 비교하는 것으로 결과는 똑같이 -1이 나온다.
그렇다면 이렇게 비교해서 어디에 쓰는 걸까?
정렬
위 두 인터페이스를 사용하는 가장 큰 이유는 원하는 대로 정렬을 할 수 있기 때문이다.
compare와 compareTo를 구현하고 sort() 메서드를 호출하면 커스텀한 대로 정렬이 된다.
먼저 Comparable를 활용해 정렬하는 코드를 짜보았다.
main() 메서드
public class Sort{
public static void main(String[] args) {
Number[] nArr = new Number[5];
for(int i = 1; i < 6; i++)
nArr[i - 1] = new Number(i);
Arrays.sort(nArr);
for(int i = 0; i < 5; i++)
System.out.print(nArr[i]);
}
}
main() 메서드에서 Number 배열인 nArr을 선언했고 각 객체에는 1~5의 값을 넣었다.
배열은 sort를 한 후 출력한다.
Number 클래스
class Number implements Comparable<Number>{
int n;
Number(int n) {
this.n = n;
}
@Override
public int compareTo(Number n) {
return this.n - n.n;
}
public String toString() {
return n + " ";
}
}
Number 클래스엔 compareTo를 선언했다.
먼저 compareTo에 return을 this.n - n.n으로 했다.
아래는 출력 결과이다.
오름차순으로 정렬이 되었다.
이번에는 return을 n.n - this.n으로 해보고 돌려보았다.
내림차순으로 정렬되었다.
compareTo의 반환 값에 따라서 결과가 다르게 나옴을 확인할 수 있다.
여기서 한 가지 더 알 수 있는 것이 있는데, sort의 정렬 기준이다.
기존 배열 nArr이 오름차순으로 정렬되어 있기 때문에 this.n - n.n < 0, n.n - this.n > 0이다.
즉, 결과가 0보다 작으면 위치를 바꾸지 않고 0보다 크면 위치를 바꾼다.
이번엔 Comparator를 이용해 보았다.
Arrays 클래스의 sort 메서드 중 comparator를 인자로 받는 것이 있어 이것을 활용했다.
전체 코드
public class Sort{
public static void main(String[] args) {
Number[] nArr = new Number[5];
for(int i = 1; i < 6; i++)
nArr[i - 1] = new Number(i);
Arrays.sort(nArr, new Comparator<Number>() {
@Override
public int compare(Number o1, Number o2) {
return o2.n - o1.n;
}
});
for(int i = 0; i < 5; i++)
System.out.print(nArr[i]);
}
}
class Number {
int n;
Number(int n) {
this.n = n;
}
public String toString() {
return n + " ";
}
}
Arrays.sort를 보면 인자에 직접 Comparator를 선언해 담은 것을 확인할 수 있다.
대부분의 경우 위와 같이 활용한다.
o2.n - o1.n의 결과는 음수이므로 위치가 바뀌고 따라서 내림차순으로 정렬된다.
Arrays.sort() 뿐만 아니라 Collections.sort()에도 똑같이 적용할 수 있다.
public class Sort{
public static void main(String[] args) {
ArrayList<Number> nArr = new ArrayList<>();
for(int i = 1; i < 6; i++)
nArr.add(new Number(i));
Collections.sort(nArr, new Comparator<Number>() {
@Override
public int compare(Number o1, Number o2) {
return o2.n - o1.n;
}
});
System.out.println(nArr.toString());
}
}
'Java > Java' 카테고리의 다른 글
Java - 정규 표현식(Regex) (0) | 2023.09.05 |
---|---|
Java - Thread에서 while문 안의 if문이 동작하지 않는 이유 (0) | 2023.09.01 |
Java - 중위 - 후위 표기법 변환 & 후위 표기법 계산 (0) | 2023.08.24 |
Java - Java 클래스, 객체, 인스턴스 (0) | 2023.07.16 |
Java - Java 배열 (0) | 2023.02.10 |