반응형

배열에 값을 넣는 방법은 알겠는데 프로그래밍을 하다 보면 배열의 정렬이 때때로 필요로 합니다.

또한 타입이 객체 타입인 경우에도 원하는 기준대로 정렬을 할 수 있도록 알아보도록 하겠습니다.

 

1. 가장 기본적인 원시 타입(int형)인 경우 배열의 오름차순 정렬을 보겠습니다.

 

int[] arr1 = {11, 5, 30, 40, 35, 80, 60};
Arrays.sort(arr1);
for(int i : arr1) {
	System.out.println(i);
}

간단합니다. Arrays.sort()함수에 배열을 넘겨주시면 됩니다.

 

arr1의 배열의 요소가 오름차순으로 정렬된 모습을 보실 수 있습니다.

sort는 기본 정렬 조건이 오름차순으로 되어 있기 때문에 특별한 코드 없이 오름차순으로 정렬이 됩니다.

 

 

2. 내림차순 정렬을 알아보겠습니다.

 

Integer[] arr2 = {11, 5, 30, 40, 35, 80, 60};
// Collections 메소드 사용
Arrays.sort(arr2, Collections.reverseOrder());

// 직접 구현도 가능
Arrays.sort(arr2, new Comparator<Integer>() {
	@Override
	public int compare(Integer i1, Integer i2) {
		return i2 - i1;
	}
});

for(int i : arr2) {
	System.out.println(i);
}

내림차순 정렬방법도 오름차순과 동일하게 진행됩니다. 하지만 인자로 내림차순이 될 수 있도록 구현된 Comparator를 넘겨 주셔야 됩니다. (Comparator가 무엇인지는 잠시 후에 살펴보겠습니다.) Comparator를 구할 때는 Collections메서드를 사용하시거나 직접 구현을 해주시면 되겠습니다.

 

 

 

3. Comparable 와 Comparator는 무엇일까?

 

위의 내용으로 배열의 정렬은 하실 수 있습니다. 이제는 정렬을 조금 더 잘 사용할 수 있도록 Comparable과 Comparator를 알아보도록 하겠습니다. 이 둘을 배우고 나면 객체도 정렬을 하실 수 있겠습니다.

Comparable과 Comparator는 정렬을 위한 인터페이스입니다. 각각의 인터페이스를 구현해서 "구현한 로직대로 정렬을 하겠다"입니다. 위에서 Arrays.sort() 함수를 통해서 정렬을 할 수 있었던 이유는 이미 Comparator가 내부적으로 구현이 되어 있기 때문입니다. 이렇게만 보면 이해가 잘 안 갑니다. 아래의 내용을 살펴보겠습니다.

 

 

4. Comparable

 

Comparable 인터페이스에는 compareTo() 추상 메소드 하나만 존재합니다.

주어진 객체(T o) 보다 작으면 음수, 같으면 0, 크면 양수를 리턴합니다.

이게 무슨말인지 소스 코드를 보겠습니다.

public class NameCard implements Comparable<NameCard> {
	public String name;
	public int age;
	
	public NameCard(String name, int age) {
		this.name = name;
		this.age = age;
	}

	@Override
	public int compareTo(NameCard o) {
		if(this.age < o.age) {
			return -1;
		} else if(this.age == o.age) {
			return 0;
		} else {
			return 1;
		}
	}
}

NameCard라는 클래스에 Comparable를 구현하였습니다. NameCard를 컬랙션에 줄줄이 넣고 정렬을 한다면 어떻게 하시겠습니까? 정렬의 기준은 어떻게 될까요? 정렬의 기준을 이름으로 할까요? 아니면 나이가 될까요? 정렬의 기준이 없습니다. 그렇기 때문에 정렬의 기준을 정하기 위해서 Comparable를 구현하는겁니다. 위의 코드를 볼 때 정렬의 기준은 나이(age)가 되겠습니다. 테스트를 하도록 하겠습니다.

 

List<NameCard> nc = new ArrayList<>();
nc.add(new NameCard("자바", 8));
nc.add(new NameCard("파이썬", 7));
nc.add(new NameCard("장고", 15));
nc.add(new NameCard("스프링", 10));

Collections.sort(nc);
for (NameCard obj : nc) {
	System.out.println(obj.name +" "+obj.age);
}

NameCard 객체를 리스트에 담아주세요. 그리고 Collections.sort() 함수를 통해서 정렬을 해주시면 되겠습니다.

 

오름차순으로 이상 없이 정렬이 된 모습을 보실 수 있습니다. 만약 내림차순을 원하시다면 compareTo 로직을 반대로 변경해주시면 됩니다.

 

 

5. Comparator

 

comparable 정렬이 일반적이고 객체에 이미 정해진 정렬이라면, Comparator는 조금 더 복잡하게 정렬도 가능하고 필요할 때마다 구현해서 사용할 수 있는 인터페이스입니다.

Comparator 인터페이스는 int compare(T t1, T t2)를 구현해주셔야 됩니다.

compareTo와 마찮가지로 t1과 t2가 같다면 0, t1이 t2 보다 앞에 오게 하려면 음수, t1이 뒤쪽으로 오게 하려면 양수를 반환하시면 됩니다.

List<NameCard> nc = new ArrayList<>();
nc.add(new NameCard("자바", 8));
nc.add(new NameCard("파이썬", 7));
nc.add(new NameCard("장고", 15));
nc.add(new NameCard("스프링", 10));

Comparator<NameCard> cp = new Comparator<>() {
	@Override
	public int compare(NameCard n1, NameCard n2) {
		return n2.age - n1.age;
	}
};

Collections.sort(nc, cp);
for (NameCard obj : nc) {
	System.out.println(obj.name +" "+obj.age);
}

코드가 조금 다른 점은 Comparator를 구현하고 sort()함수에 인자로 같이 넘겨줬습니다.

익명 객체라 하여 이름 있는 객체를 만드는 것이 아닌, 객체를 바로 생성하였습니다. 그리고 sort() 함수에 전달을 했는데요. 기존에 NameCard에 comparable이 구현이 되어 있음에도 불구하고 Comparator이 적용된 모습을 보실 수 있습니다.

 

 

Comparator 인터페이스는 코드 작성 중 정렬이 필요할 때마다 위와 같이 익명 객체로 구현해서 적용을 해주시면 더 편리하게 정렬이 가능하겠습니다.

 

감사합니다.

반응형

+ Recent posts