22.5.05 [HackerRank]Java Sort

서태욱·2022년 5월 6일
0

Algorithm

목록 보기
30/45
post-thumbnail

✅ 문제 분석

ID, 이름, CGPA(누적 학점 평균)같은 학생 정보가 제공된다.
이 정보를 CGPA에 따라서 내림차순으로 재배열하는 문제다.
만약 두 학생의 CGPA가 같으면 이름에 따라서 알파벳 순으로 정리하고,
이름마저 같으면 ID에 따라서 순서를 정한다. (ID는 각기 고유한 값임)
comparator를 사용한다.

첫줄에 입력되는 정수는 총 학생수다.
다음 줄마다 ID Name CGPA 순으로 학생 정보가 입력된다.
이름은 소문자만 포함되고 id는 0으로 시작하지 않는다. CGPA는 소수점 이하 2자리까지 표시된다.

🌱 배경지식

Java Comparator

객체를 비교할 수 있도록 만들어진 인터페이스다.
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;
	}
}

Sort

  • Arrays.sort()
  • Collections.sort()

기본적으로 오름차순 정렬이다.
내림차순하려면 직접 정의하거나, 아래와 같이 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());
        }
    }
}

👉 참고

profile
re:START

0개의 댓글