[Java] 요소가 맵인 List 정렬하기

Published: by Creative Commons Licence

List의 구성요소를 정렬해야 할 때 구성요소의 타입이 기본형 혹은 String 일 땐 Collections.sort(List<?> list) 메서드를 사용하면 간단하게 해결된다. 하지만 요소가 String이 아닌 맵 타입이라면 어떻게 해야 할까?

ArrayList<HashMap<String, String>> 타입을 예로 들면:

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

public class Test {
    public static void main(String[] args) throws Exception {
        HashMap<String, String> map = new HashMap<String, String>();

        ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
        map.put("no", "3");
        map.put("title", "test3");
        list.add(map);
        map = new HashMap<String, String>();
        map.put("no", "1");
        map.put("title", "test1");
        list.add(map);
        map = new HashMap<String, String>();
        map.put("no", "2");
        map.put("title", "test2");
        list.add(map);
        System.out.println(list);

        MapComparator comp = new MapComparator("no");
        Collections.sort(list, comp);
        System.out.println(list);
    }
}

class MapComparator implements Comparator<HashMap<String, String>> {
    private final String key;

    public MapComparator(String key) {
        this.key = key;
    }

    @Override
    public int compare(HashMap<String, String> first, HashMap<String, String> second) {
        int result = first.get(key).compareTo(second.get(key));
        return result;
    }
}

// [{title=test3, no=3}, {title=test1, no=1}, {title=test2, no=2}]
// [{title=test1, no=1}, {title=test2, no=2}, {title=test3, no=3}]

Collections.sort() 메서드에 인터페이스 Comparator를 implement하는 클래스를 인자값으로 추가한다. 여기서 MapComparator 클래스를 살펴보면 해시맵에서 키에 대응하는 값을 가져오기 위해 생성자 블록으로 키 값을 받아 처리하게 해놨다. 오버라이드 메서드인 compare()는 int형 결과를 반환하며 이는 Collections.sort() 메서드에서 사용된다.

public static void main(String[] args) throws Exception {
    HashMap<String, String> map = new HashMap<String, String>();

    ArrayList<HashMap<String, String>> list = new ArrayList<HashMap<String, String>>();
    map.put("no", "3");
    map.put("title", "test3");
    list.add(map);
    map = new HashMap<String, String>();
    map.put("no", "1");
    map.put("title", "test1");
    list.add(map);
    map = new HashMap<String, String>();
    map.put("no", "2");
    map.put("title", "test2");
    list.add(map);
    System.out.println(list);

    Collections.sort(list, new Comparator<HashMap<String, String>>() {
        @Override
        public int compare(HashMap<String, String> first,
                HashMap<String, String> second) {

            return first.get("no").compareTo(second.get("no"));
        }
    });

    System.out.println(list);
}

인터페이스인 Comparator의 구현체 작성을 생략하기 위한 익명-중첩 클래스 형식의 코드다. 작동방식은 첫 번째 예시와 같다.

위의 예시들은 모두 오름차순 정렬이며 내림차순 정렬은 return 값을 수정하는 것으로 구현할 수 있다. Comparator 인터페이스를 implements 하며 compare() 메서드를 오버라이드 한 뒤 두 값 중 앞의 것이 크면 -1, 같으면 0, 뒤의 것이 크면 1을 반환한다. (오름차순은 이와 반대다. 앞의 것이 크면 1 뒤의 것이 크면 -1)

Collections.sort(list, new Comparator<HashMap<String, String>>() {
     @Override
     public int compare(HashMap<String, String> first,
             HashMap<String, String> second) {

         int firstValue = Integer.valueOf(first.get("no"));
         int secondValue = Integer.valueOf(second.get("no"));

         // 내림차순 정렬
         if (firstValue > secondValue) {
             return -1;
         } else if (firstValue < secondValue) {
             return 1;
         } else /* if (firstValue == secondValue) */ {
             return 0;
         }
     }
});

example

List<String> 내림차순 정렬

ArrayList<string> list = new ArrayList<string>();
// list.add....
// list.add....

Collections.sort(list, new Comparator<string>() {
    @Override
    public int compare(String o1, String o2) {
        int firstValue = 0;
        int secondValue = 0;

        firstValue = (int) o1.charAt(0);
        secondValue = (int) o2.charAt(0);

        // 내림차순 정렬
        if (firstValue > secondValue) {
            return -1;
        } else if (firstValue < secondValue) {
            return 1;
        } else /* if (firstValue == secondValue) */ {
            return 0;
        }
    }
});