언어/Java의 정석

Chapter 11) 컬렉션 프레임워크 - TreeMap

아는개발자 2023. 5. 21. 21:16

◇ TreeMap

이름에 Tree가 붙은 만큼 이진검색트리의 형태로 키와 값의 쌍으로 이루어진 데이터를 저장

검색에 관한한 대부분의 경우 HashMap이 TreeMap보다 더 뛰어나므로 HashMap을 사용하는 것이 좋다.

다만 범위 검색이나 정렬이 필요한 경우에는 TreeMap을 사용하자.

 

◇ 자주 찾을만한 함수

  • Key 찾기
    • ceilingKey(Object key): key와 일치하거나 큰 key 중 제일 작은 key를 반환. 없으면 null
    • floorKey(Object key): key와 일치하거나 작은 key 중 제일 큰 key를 반환. 없으면 null
    • higherKey(Object key): 지정된 key보다 큰 key 중에서 제일 작은 key를 반환. 없으면 null
    • lowerKey(Object key): 지정된 key보다 작은 key 중에서 제일 큰 key를 반환. 없으면 null
    • firstKey(): 가장 작은 키 반환
    • lastKey(): 가장 큰 키 반환
  • Entry 찾기
    • pollFirstEntry(): 제일 작은 키를 제거하면서 반환
    • pollLastEntry(): 제일 큰 키를 제거하면서 반환
  • 교체
    • replace(Object k, Object v): 기존의 key(k)를 지정된 값(v)으로 변경
    • replace(Object k, Object oldValue, Object newValue): 기존의 key(k)를 지정된 값(newValue)으로 변경. 단, 기존의 값이 oldValue값과 일치해야 함.
import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] data= {"A", "K", "A", "K", "D", "K", "A", "K", "K", "K", "Z", "D"};

        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i=0, iMax = data.length; i<iMax; i++){
            String key = data[i];
            if(map.containsKey(key)){
                map.replace(key, map.get(key)+1);
            }
            else{
                map.put(key, 1);
            }
        }

        Iterator it = map.entrySet().iterator();
        System.out.println("기본 정렬");
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = (Map.Entry)it.next();
            int value = entry.getValue();
            System.out.println(entry.getKey() + ": "+ printBar('#', value)+" "+value);
        }
        System.out.println();
    }

    private static String printBar(char c, int n){
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<n; i++){
            sb.append(c);
        }
        return sb.toString();
    }
}

예제 출력 결과.

import java.util.*;

public class Main {

    public static void main(String[] args) {
        String[] data= {"A", "K", "A", "K", "D", "K", "A", "K", "K", "K", "Z", "D"};

        TreeMap<String, Integer> map = new TreeMap<>();
        for(int i=0, iMax = data.length; i<iMax; i++){
            String key = data[i];
            if(map.containsKey(key)){
                map.replace(key, map.get(key)+1);
            }
            else{
                map.put(key, 1);
            }
        }

        Set set =  map.entrySet();
        List list = new ArrayList(set);
        Collections.sort(list, new ValueComparator());

        Iterator it = list.iterator();
        System.out.println("값의 크기가 큰 순서로 정렬 정렬");
        while(it.hasNext()){
            Map.Entry<String, Integer> entry = (Map.Entry)it.next();
            int value = entry.getValue();
            System.out.println(entry.getKey() + ": "+ printBar('#', value)+" "+value);
        }
        System.out.println();
    }

    static class ValueComparator implements Comparator{
        public int compare(Object o1, Object o2){
            if(o1 instanceof Map.Entry && o2 instanceof Map.Entry){
                Map.Entry m1 = (Map.Entry)o1;
                Map.Entry m2 = (Map.Entry)o2;
                return (Integer)m2.getValue() - (Integer)m1.getValue();
            }
            return -1;
        }
    }

    private static String printBar(char c, int n){
        StringBuilder sb = new StringBuilder();
        for(int i=0; i<n; i++){
            sb.append(c);
        }
        return sb.toString();
    }
}

예제 출력2

문제 중 빈도수가 높은 것을 표현하되 값이 동일한 경우 사전 순서가 먼저 오는 순으로 출력하는 경우 이 자료구조를 사용해도 될 것 같다는 생각이 들었다.