본문 바로가기
프로그래밍/자바

ArrayList 정렬(Sort) 하기

by pentode 2018. 4. 12.

ArrayList에 포함된 요소들을 정렬하는 방법을 알아보겠습니다. 대부분의 웹 애플리케이션들은 데이터베이스에서 정렬된 데이터를 조회하여 ArrayList에 담아서 사용하므로 ArrayList 자체를 정렬할 일은 잘 없습니다. 하지만 가끔씩 리스트를 직접 정렬해야 할일이 생깁니다.


ArrayList 를 정렬하는데는 Collections.sort() 메소드를 사용합니다. 이 sort() 메소드의 인자로 정렬할 리스트를 넘기게 되는데, 오버로딩된 두 가지 버전의 메소드가 있습니다.


첫 번째는 하나의 인자를 받는데, Comparable 인터페이스를 구현하고 있는 요소를 가지는 리스트를 인자로 주게 됩니다. 두 번째는 두개의 인자를 받는데, 첫 번째 인자는 리스트 객체이고, 두 번째 인자는 리스트내의 각 요소를 비교하는데 사용하게 될 Comparator 인터페이스를 구현한 객체를 넘기게 됩니다. 이 때 리스트내의 요소는 Comparable 인터페이스를 구현할 필요가 없습니다.


각각을 예제로 알아보도록 하겠습니다.



1. Comparable 인터페이스를 구현하는 요소를 가지는 리스트를 정렬

 

package com.tistory.pentode.test;

import java.util.ArrayList;
import java.util.Collections;

public class Main {
    public static void main(String[] args) {
        // 테스트용 데이터를 만듭니다.
        ArrayList boardList = new ArrayList();
        boardList.add(new Board(1, "홍길동", "2016-01-02"));
        boardList.add(new Board(2, "아무개", "2017-03-05"));
        boardList.add(new Board(3, "김영희", "2015-12-15"));
        boardList.add(new Board(4, "김철수", "2016-10-05"));

        // 리스트를 정렬합니다.
        Collections.sort(boardList);

        // 정렬된 내용을 출력해 봅니다.
        for(Board board : boardList) {
            System.out.println(board);
        }
    }
}

// 리스트에 저장될 클래스 입니다.
class Board implements Comparable {
    private int num;
    private String name = "";
    private String date = "";

    public Board(int num, String name, String date) {
        this.num = num;
        this.name = name;
        this.date = date;
    }

    /**
     * Comparable 인터페이스에 정의된 compareTo 메소드를 오버라이드 합니다.
     */
    @Override
    public int compareTo(Board board) {
        return this.name.compareTo(board.name);
    }

    //  getter, setter를 정의합니다.
    public void setNum(int num) { this.num = num; }
    public int getNum() { return this.num; }
    public void setname(String name) { this.name = name; }
    public String getName() { return this.name; }
    public void setDate(String date) { this.date = date; }
    public String getDate() { return this.date; }

    // 객체의 내용을 출력합니다.
    public String toString() {
        StringBuilder sb = new StringBuilder();
        sb.append(this.num).append(" : ");
        sb.append(this.name).append(" : ");
        sb.append(this.date);
        return sb.toString();
    }
}

 

결과

 

3 : 김영희 : 2015-12-15
4 : 김철수 : 2016-10-05
2 : 아무개 : 2017-03-05
1 : 홍길동 : 2016-01-02

 

Comparable 인터페이스를 구현해서 오버라이딩 해야 하는  메소드가 compareTo() 메소드 입니다. 정수값을 반환하는데, 자신과 인자로 주어진 자신과 같은 타입의 객체를 비교하여 같으면 0, 자신이 크면 양수, 자신이 작으면 음수를 반환하도록 만들면 됩니다. 이 예제에서는 이름을 비교하여 오름차순으로 정렬합니다.

 

@Override
public int compareTo(Board board) {
    return this.name.compareTo(board.name);
}

 

2. Comparator를 사용한 정렬

 

package com.tistory.pentode.test;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class Main {
    public static void main(String[] args) {
        // 테스트용 데이터를 만듭니다.
        ArrayList boardList = new ArrayList();
        boardList.add(new Board(1, "홍길동", "2016-01-02"));
        boardList.add(new Board(2, "아무개", "2017-03-05"));
        boardList.add(new Board(3, "김영희", "2015-12-15"));
        boardList.add(new Board(4, "김철수", "2016-10-05"));

        // 두 번째 인자로 Comparator 객체를 익명객체로 만들어서 넘깁니다.
        Collections.sort(boardList, new Comparator() {
            @Override
            public int compare(Board b1, Board b2) {
                return b1.getDate().compareTo(b2.getDate());
            }
        });

        // 결과를 출력합니다.
        for(Board board : boardList) {
            System.out.println(board);
        }
    }
}

// 이번에는 저장될 객체가  Comparable 인터페이스를 구현하지 않습니다.
class Board {
	private int num;
	private String name = "";
	private String date = "";
	
	public Board(int num, String name, String date) {
		this.num = num;
		this.name = name;
		this.date = date;
	}
	
	public void setNum(int num) { this.num = num; }
	public int getNum() { return this.num; }
	public void setname(String name) { this.name = name; }
	public String getName() { return this.name; }
	public void setDate(String date) { this.date = date; }
	public String getDate() { return this.date; }
	
	public String toString() {
		StringBuilder sb = new StringBuilder();
		sb.append(this.num).append(" : ");
		sb.append(this.name).append(" : ");
		sb.append(this.date);
		return sb.toString();
	}
}

 

결과

 

3 : 김영희 : 2015-12-15
1 : 홍길동 : 2016-01-02
4 : 김철수 : 2016-10-05
2 : 아무개 : 2017-03-05

 

Comparator 인터페이스는를 구현하는 익명객체는 compare() 메소드를 오버라이딩 해야 합니다. compare() 메소드는 두 개의 인자를 받아서 비교 후 정수 반환 값을 반환 합니다. 이것도 역시 둘 이 같다면 0을 반환하고, 첫 번째 인자가 크다면 양수를, 두 번째 인자가 크다면 음수를 반환하면 됩니다. 이 예제에서는 날짜를 비교하여 오름차순으로 정렬합니다.

 

Collections.sort(boardList, new Comparator() {
    @Override
    public int compare(Board b1, Board b2) {
        return b1.getDate().compareTo(b2.getDate());
    }
});

 

지금까지 ArrayList 를 정렬하는 방법에 대해서 알아 보았습니다. 앞의 두 예제에서 Comparable 인터페이스의 comparTo() 메소드와 Comparator 인터페이스의 compare() 메소드 를 구현하는데 있어서, 실제 사용을 위해서는 인자의 null 체크 및 타입 체크를 넣어서 좀더 안전한 코드를 만들어야 할 것입니다.


위의 두 예제는 모두 대상 필드를 기준으로 오름차순으로 정렬하는데, 반대로 정렬하려고 한다면 두 가지 방법이 있겠습니다. 첫 번째는 비교 메소드의 반환값의 음수, 양수 부호를 반대로 하면 되겠습니다. 두 번째는 오름 차순으로 정렬한 다음에 Collections.reverse() 메소드를 사용해서 순서를 뒤집으면 되겠습니다.

반응형