Java/컬렉션

[Java]HashMap 키(Key) 정렬 방법

DevStory 2022. 4. 4.

이번 포스팅에서는 Java에서 HashMap 키를 기준으로 정렬하는 방법을 소개합니다.


순서를 보장하지 않는 HashMap

HashMap은 순서를 보장하지 않습니다. 아래 간단한 HashMap 예제를 보면 삽입 순서대로 출력되지 않는 것을 확인할 수 있습니다.

Map<String, Integer> map = new HashMap<>();

map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);

System.out.println(map);

실행 결과

{Tom=27, John=34, Bill=29, Jane=26}

키의 타입을 String으로 값의 타입을 Interger로 정의하였습니다. 대부분 개발자는 HashMap의 키 타입을 String 또는 Integer로 설정하고 값은 객체(Object) 또는 String, Integer 타입으로 설정합니다.

 

HashMap은 어떠한 경우에도 키 또는 값을 기준으로 정렬되지 않습니다. HashMap은 키의 해시 값을 기반으로 요소를 정렬하기 때문입니다.


TreeMap을 사용하여 정렬

TreeMap은 SortedMap 인터페이스를 상속받는 클래스입니다.

문자열 사전 순으로 키 정렬 

TreeMap에 Comparator를 생략하면 기본 Comparator가 동작합니다. Comparator에서 문자열을 비교하는 경우 compareTo() 메서드가 실행됩니다. 이 메서드는 문자열을 사전 순으로 비교하고 오름차순으로 정렬합니다.

List<String> li = new ArrayList<String>(
        Arrays.asList("John", "Jane", "Tom", "Bill")
);

Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);

Map<String, Integer> sortedMap = new TreeMap<>(map);

System.out.println(sortedMap);

실행 결과

{Bill=29, Jane=26, John=34, Tom=27}
반응형

개발자 정의

개발자가 TreeMap에 new Comparator<T>()를 전달하여 정렬 로직을 직접 구현할 수 있습니다. 다음 예제는 문자열의 길이와 개발자가 직접 정의한 Comparator를 사용하여 HashMap 키를 길이별로 정렬합니다.

Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);

Map<String, Integer> sortedMap = new TreeMap<>(new Comparator<String>() {
  @Override
  public int compare(String o1, String o2) {
    int lengthDifference = o1.length() - o2.length();
    if (lengthDifference != 0) return lengthDifference;
    return o1.compareTo(o2);
  }
});

sortedMap.putAll(map);

System.out.println(sortedMap);

실행 결과

{Tom=27, Bill=29, Jane=26, John=34}

TreeMap 클래스에 Comparator을 사용하여 comapre() 메서드를 재정의(Override)합니다. 재정의된 compare() 메서드는 문자열의 길이를 비교하고 문자열의 길이가 동일하면 사전 순으로 비교합니다.

 

정렬 로직을 정의했으면 후 putAll() 메서드를 사용하여 map의 모든 요소를 sortedMap에 삽입합니다. 삽입된 map 요소는 개발자가 재정의한 compare() 메서드를 통해 정렬됩니다.


LinkedHashMap을 사용하여 정렬

LinkedHashMap은 삽입 순서를 유지하는 클래스입니다. LinkedHashMap 클래스는 이중 연결 리스트 방식으로 데이터를 관리하므로 요소를 접근하는데 유용하게 사용할 수 있습니다.


문자열 사전 순으로 키 정렬

Map.Entry 클래스에는 comparingByKey() 메서드가 존재합니다. 이 메서드는 키를 비교하기 위해 사용되는 메서드입니다.

 

키의 타입을 String으로 정의하였기 때문에 키를 사전 순으로 정렬합니다.

Map<String, Integer> map = new HashMap<>();
map.put("John", 34);
map.put("Jane", 26);
map.put("Tom", 27);
map.put("Bill", 29);

Map<String, Integer> sortedMap = map.entrySet().stream()
        .sorted(Map.Entry.comparingByKey())
        .collect(Collectors.toMap(
                Map.Entry::getKey,
                Map.Entry::getValue,
                (a, b) -> { throw new AssertionError(); },
                LinkedHashMap::new
        ));

System.out.println(sortedMap);

실행 결과

{Bill=29, Jane=26, John=34, Tom=27}
반응형

댓글