일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
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 |
- 도커
- 백엔드
- CI/CD
- 가상화
- Java
- spring boot
- JPA
- Container
- 배포
- HTTP
- 스프링 부트
- 컨테이너
- Spring
- 스프링 시큐리티
- computer science
- spring batch
- vm
- web server
- 웹 서버
- 스프링 배치
- 자바
- spring cloud
- 스프링
- virtualization
- 영속성 컨텍스트
- ORM
- 데이터베이스
- mysql
- Spring Security
- CS
- Today
- Total
개발 일기
[Java] 자바 코테를 위한 정렬(Sorting) 및 Comparable와 Comparator 본문
Array 배열에서의 정렬 - 단일 기준
// 오름차순 정렬
int arr[] = {5,3,2,4,1};
Arrays.sort(arr); // [1,2,3,4,5]
// 내림차순 정렬
Integer arr[] = {5,3,2,4,1};
Arrays.sort(arr, Collections.reverseOrder()); // [5,4,3,2,1]
그러나 위 코드에서도 알 수 있듯이 내림차순 정렬의 Collections.reverseOrder()는 객체 형태에게만 가능하기 때문에 기본형인 int가 아닌 참조형 변수 즉, 객체 타입인 Integer배열로 선언한 것을 알 수 있다.
그래서 아래와 같이 처리할 수 있긴한데 그래도 코드가 길고 번거로워진다.
int arr[] = {5,3,2,4,1};
Integer[] temp = Arrays.stream(arr).boxed.toArray(Integer[]::new);
Arrays.sort(temp, Collections.reverseOrder());
- int는 기본 데이터 타입(Primitive Data Type) 이기 때문에 객체 배열을 정렬할때 사용되는 `Arrays.sort(T[] arr, Comparator<? super T> c)`를 사용하여 배열할 수 없어 Integer 객체 배열로 전환 후에 사용해주어야 한다.
그래서 이번엔 원래 기본형으로 생성된 배열에 -1을 모든 요소에 곱해준 뒤 똑같이 오름차순 정렬을 해준 뒤 그 결과에 다시 -1을 곱하면 성공적으로 오름차순 정렬에 성공할 수 있다.
// 오름차순 정렬
int arr[] = {5,3,2,4,1};
Arrays.sort(arr); // [1,2,3,4,5]
// 모든 요소에 -1을 곱함
for (int i = 0; i < arr.length; i++) {
arr[i] *= -1;
}
// 오름차순 정렬 (결과적으로 내림차순 효과)
Arrays.sort(arr);
// 다시 모든 요소에 -1을 곱해 원래 값으로 변환
for (int i = 0; i < arr.length; i++) {
arr[i] *= -1;
}
System.out.println(Arrays.toString(arr)); // [5, 4, 3, 2, 1]
컬렉션에서의 정렬
리스트 같은 컬렉션을 정렬할 때는 Collections.sort()를 사용할 수 있다.
List<String> list = new LinkedList<String>();
list.add(“김철수”);
list.add(“김영희”);
Collections.sort(list);
Collections.reverse(list);
내림차순 정렬은 더 쉬운 편이다. reverse() 라는게 따로 있다.
아니면 마찬가지로 이렇게도 가능하다.
List.sort()
참고로, 리스트 같은 경우는 자체 sort 메서드가 있다. 따라서 굳이 Collections.sort()를 사용하지 않아도 된다. Java 8 이후에 생겼다고 함.
List<String> list = new LinkedList<String>();
list.sort(Comparator.naturalOrder()); // 오름차순 정렬
list.sort(Comparator.reverseOrder()); // 내림차순 정렬
list.sort(String.CASE_INSENSITIVE_ORDER); // 대소문자 구분없이 내림차순 정렬
list.sort(Collections.reverseOrder(String.CASE_INSENSITIVE_ORDER)); // 대소문자 구분없이 내림차순 정렬
Comparable와 Comparator
자바 정렬을 제대로 이해하려면 Comparable와 Comparator을 알아야 한다. 그리고... 객체 정렬 같이 복잡한 정렬이 필요한 경우도 이 개념에 대해 알고 있어야 된다.
Comparable과 Comparator는 모두 인터페이스(interface).
즉, Comparable 혹은 Comparator을 사용하고자 한다면 인터페이스 내에 선언된 메소드를 '반드시 구현'
Comparator
우선 Comparator부터 살펴보자.
사용자가 직접 Comparator Interface를 implements하여 Comparator를 만들 수 있다.
이 Comparator는 Collections.sort() 또는 List.sort() 메소드의 파라미터로 전달되어, 정렬의 기준이 된다.
이때 Comparator의 compare 메소드를 오버라이딩할때
- Integer를 비교할 경우 Integer.compare(i1,i2);
- String을 비교할 경우 s1.compareTo(S2);
로 비교를한다.
import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;
public class SortCarList {
public static void main(String[] args) {
// ArrayList 준비
ArrayList<Car> list = new ArrayList<>();
list.add(new Car("BMW", 50000, 240));
list.add(new Car("Tesla", 80000, 260));
list.add(new Car("Hyundai", 30000, 200));
System.out.println("원본 : " + list);
// [[ BMW: 50000, 240km/h ], [ Tesla: 80000, 260km/h ], [ Hyundai: 30000, 200km/h ]]
// price순 오름차순 정렬
Collections.sort(list, new CarPriceComparator());
System.out.println("price 순 오름차순 : " + list);
// [[ Hyundai: 30000, 200km/h ], [ BMW: 50000, 240km/h ], [ Tesla: 80000, 260km/h ]]
// speed순 내림차순 정렬
Collections.sort(list, new CarSpeedComparator().reversed());
System.out.println("speed 순 내림차순 : " + list);
// [[ Tesla: 80000, 260km/h ], [ BMW: 50000, 240km/h ], [ Hyundai: 30000, 200km/h ]]
// brand순 오름차순 정렬
Collections.sort(list, new CarBrandComparator());
System.out.println("brand 순 오름차순 : " + list);
// [[ BMW: 50000, 240km/h ], [ Hyundai: 30000, 200km/h ], [ Tesla: 80000, 260km/h ]]
// brand순 내림차순 정렬
Collections.sort(list, new CarBrandComparator().reversed());
System.out.println("brand 순 내림차순 : " + list);
// [[ Tesla: 80000, 260km/h ], [ Hyundai: 30000, 200km/h ], [ BMW: 50000, 240km/h ]]
}
}
// 가격 정렬 Comparator
class CarPriceComparator implements Comparator<Car> {
@Override
public int compare(Car c1, Car c2) {
return Integer.compare(c1.price, c2.price);
}
}
// 속도 정렬 Comparator
class CarSpeedComparator implements Comparator<Car> {
@Override
public int compare(Car c1, Car c2) {
return Integer.compare(c1.speed, c2.speed);
}
}
// 브랜드 정렬 Comparator
class CarBrandComparator implements Comparator<Car> {
@Override
public int compare(Car c1, Car c2) {
return c1.brand.compareTo(c2.brand);
}
}
// 자동차 클래스
class Car {
String brand; // 자동차 브랜드
int price; // 가격
int speed; // 최고 속도
public Car(String brand, int price, int speed) {
this.brand = brand;
this.price = price;
this.speed = speed;
}
@Override
public String toString() {
return "[ " + this.brand + ": " + this.price + ", " + this.speed + "km/h ]";
}
}
Comparable
Collections.sort() 메소드는 객체를 정렬할 때, 해당 객체의 Comparable을 구현한 compareTo() 메소드를 참조하여, 정렬 순서를 결정한다.
따라서, 정렬할 객체가 Comparable interface를 구현하고, compareTo() 메소드 안에 정렬 기준이 정의된다면, Collections.sort() 메소드를 사용하여 객체를 정렬할 수 있다.
Comparable 인터페이스를 쓰려면 compareTo 메소드를 구현해야한다. Comparable의 compareTo(T o) 메소드는 파라미터(매개변수)가 한 개이고, Comparator의 compare(T o1, T o2) 메소드는 파라미터가 두개라는 차이가 있다.
왜 이렇게 구분되는걸까? Comparable은 "자기 자신과 매개변수 객체를 비교"하는 것이고, Comparator는 "두 매개변수 객체를 비교"한다는 것이다. 즉, 본질적으로 비교한다는 것 자체는 같지만, 비교 대상이 다르다는 것이다. 또 다른 차이점이라면 Comparable은 lang패키지에 있기 때문에 import 를 해줄 필요가 없지만, Comparator는 util패키지에 있다.
class Student implements Comparable<Student> {
int age; // 나이
int classNumber; // 학급
Student(int age, int classNumber) {
this.age = age;
this.classNumber = classNumber;
}
@Override
public int compareTo(Student o) {
/*
* 만약 자신의 age가 o의 age보다 크다면 양수가 반환 될 것이고,
* 같다면 0을, 작다면 음수를 반환할 것이다.
*/
return this.age - o.age;
}
}
그러면 이를 sort하면 자동으로 해당 compareTo 정의에 따라 sort가 된다.
ArrayList<Student> list = new ArrayList<>();
list.add(new Student(12, 1));
list.add(new Student(13, 3));
list.add(new Student(11, 2));
Collections.sort(list);
'Back-End > Java' 카테고리의 다른 글
[Java] JVM 메모리 구조(Method-Static, Heap, Stack) (2) | 2024.11.06 |
---|---|
[Java] HashMap 시간복잡도 (0) | 2024.10.31 |
[Java] 자바에서 스택(Stack), 큐(Queue), 덱(Deque) 그리고 우선순위큐(PriorityQueue) (0) | 2024.10.24 |
[Java] List 인터페이스 구현체 - ArrayList와 LinkedList (0) | 2024.10.23 |
[Java] 자료 구조 - Array와 Collection Framework의 인터페이스들 (1) | 2024.10.22 |