ID, 이름, CGPA(누적 학점 평균)같은 학생 정보가 제공된다.
이 정보를 CGPA에 따라서 내림차순으로 재배열하는 문제다.
만약 두 학생의 CGPA가 같으면 이름에 따라서 알파벳 순으로 정리하고,
이름마저 같으면 ID에 따라서 순서를 정한다. (ID는 각기 고유한 값임)
comparator를 사용한다.
첫줄에 입력되는 정수는 총 학생수다.
다음 줄마다 ID Name CGPA 순으로 학생 정보가 입력된다.
이름은 소문자만 포함되고 id는 0으로 시작하지 않는다. CGPA는 소수점 이하 2자리까지 표시된다.
객체를 비교할 수 있도록 만들어진 인터페이스다.
compare(T o1, T o2)메소드 하나가 선언되어 있다.
자기 자신이 아니라, 매개변수로 들어오는 o1, o2를 비교한다.
익명 객체를 사용하는 방법이 권장된다.
익명 객체를 main 내부에 지역변수로 만들거나 / main 밖에서 static으로 선언 후 사용 가능
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
// 익명 객체 구현방법 1
Comparator<Student> comp1 = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.classNumber - o2.classNumber;
}
};
}
// 익명 객체 구현 2
public static Comparator<Student> comp2 = new Comparator<Student>() {
@Override
public int compare(Student o1, Student o2) {
return o1.classNumber - o2.classNumber;
}
};
}
// 외부에서 익명 객체로 Comparator가 생성되기 때문에 클래스에서 Comparator을 구현 할 필요가 없어진다.
class Student {
int age; // 나이
int classNumber; // 학급
Student(int age, int classNumber) {
this.age = age;
this.classNumber = classNumber;
}
}
기본적으로 오름차순 정렬이다.
내림차순하려면 직접 정의하거나, 아래와 같이 reverseOrder()사용.
Comparable / Comparator 에서 반환값의 부호를 바꿔줘야 함
미리 정의된 Comparator 사용 --> Collections.reverseOrder()
: Arrays.sort(arr, Collections.reverserOrder())
정렬 예시
import java.util.Arrays;
import java.util.Comparator;
public class Test {
public static void main(String[] args) {
MyInteger[] arr = new MyInteger[10];
// 객체 배열 초기화 (랜덤 값으로)
for(int i = 0; i < 10; i++) {
arr[i] = new MyInteger((int)(Math.random() * 100));
}
// 정렬 이전
System.out.print("정렬 전 : ");
for(int i = 0; i < 10; i++) {
System.out.print(arr[i].value + " ");
}
System.out.println();
// MyInteger에 대한 Comparator을 구현한 익명객체를 넘겨줌
Arrays.sort(arr, comp);
// 정렬 이후
System.out.print("정렬 후 : ");
for(int i = 0; i < 10; i++) {
System.out.print(arr[i].value + " ");
}
System.out.println();
}
static Comparator<MyInteger> comp = new Comparator<MyInteger>() {
@Override
public int compare(MyInteger o1, MyInteger o2) {
return o1.value - o2.value;
}
};
}
class MyInteger {
int value;
public MyInteger(int value) {
this.value = value;
}
}
자바 8 람다를 이용한 정렬 예시
import java.util.Arrays;
import java.util.Comparator;
import java.util.List;
/**
* [ Lambda 의 기본 틀 ]
* Predicate : (T -> boolean) -> 주로 필터에 사용
* Supplier : (() -> T) -> 만드는놈(객체 생성)
* Consumer : (T -> void) -> 쓰는놈(실행에 사용)
* Function : (T -> R) -> From 에서 뭔가를 To 로 만들어 넘김
*/
public class Main {
public static class Apple {
private String color;
private Integer weight;
public Apple() {}
public Apple(String color, Integer weight) {
this.color = color;
this.weight = weight;
}
public String getColor() {
return color;
}
public Integer getWeight() {
return weight;
}
@Override
public String toString() {
return "Apple{" +
"color='" + color + '\'' +
", weight=" + weight +
'}';
}
}
public static void main(String[] args) throws Exception {
List<Apple> inventory = Arrays.asList(new Apple("green", 50), new Apple("gray", 50), new Apple("pink", 100));
// 무게 오름차순 정렬
inventory.sort(Comparator.comparing(Apple::getWeight));
// 무게 내림차순 정렬
inventory.sort(Comparator.comparing(Apple::getWeight).reversed());
// 무게 오름차순 정렬 (무게가 같으면 색 오름차순 정렬)
inventory.sort(Comparator.comparing(Apple::getWeight).thenComparing(Apple::getColor));
// 무게 오름차순 정렬 (무게가 같으면 색 내림차순 정렬)
Comparator<Apple> reversedColorComparator = Comparator.comparing(Apple::getColor).reversed();
inventory.sort(Comparator.comparing(Apple::getWeight).thenComparing(reversedColorComparator));
for (Apple apple : inventory) {
System.out.println(apple.toString());
}
}
}
출처: https://broduck.tistory.com/6 [개발로 하는 개발]
import java.sql.Struct;
import java.util.*;
class Student{
private int id;
private String fname;
private double cgpa;
public Student(int id, String fname, double cgpa) {
super();
this.id = id;
this.fname = fname;
this.cgpa = cgpa;
}
public int getId() {
return id;
}
public String getFname() {
return fname;
}
public double getCgpa() {
return cgpa;
}
}
//Complete the code
public class JavaSort {
public static void main(String[] args){
Scanner in = new Scanner(System.in);
int testCases = Integer.parseInt(in.nextLine());
List<Student> studentList = new ArrayList<Student>();
while(testCases>0){
int id = in.nextInt();
String fname = in.next();
double cgpa = in.nextDouble();
Student st = new Student(id, fname, cgpa);
studentList.add(st);
testCases--;
}
studentList.sort(new Comparator<Student>() {
@Override // 수퍼 클래스인 compare 메소드를 오버라이드 compare메소드를 아래 정의한대로 사용하겠다! + 컴파일 시 문법 체크 for 오류 방지
public int compare(Student s1, Student s2) {// compare() 메서드는 Comparator 인터페이스를 구현할 때 구현해야하는 메서드다.
if (s1.getCgpa() == s2.getCgpa()) { //cgpa순으로 비교 해서 같은 경우
int nameCompare = s1.getFname()
.compareTo(s2.getFname());
if (nameCompare == 0)
return s1.getId() - s2.getId(); //이름이 같을 경우에는 학번 오름차순
else return nameCompare;
} else { // cgpa가 같지 않다면 비교를 위해 소수점 두자리의 실수인 cgpa에 1000을 곱한 뒤 비교해준다.
return (int) (s2.getCgpa() * 1000 - s1.getCgpa() * 1000);
// compare 메소드를 오버라이딩 했기 때문에 리턴 타입을 int로 받아야 한다. 따라서 *1000을 해준 것. 내림차순 해줘야 하므로 매개변수 순서를 바꾼다. (s2-s1)
}
}
});
// 자바8부터 사용 가능한 람다를 이용한 다중조건 정렬
// Collections.sort(studentList, Comparator
// .comparing(Student::getCgpa).reversed() // 기본이 오름차순이므로 내림차순 정렬 하려면 reversed()를 해줘야 한다.
// .thenComparing(Student::getFname) //Comparator interface의 comparing이라는 static method사용.
// .thenComparing(Student::getId));
for(Student st: studentList){
System.out.println(st.getFname());
}
}
}