검색 기능을 강화시킨 컬렉션
TreeSet, TreeMap -> 이진트리 (binary tree) 사용하기 때문에 검색 속도 향상
이진 트리 구조
부노 노드와 자식 노드로 구성
왼쪽 자식 노드: 부모 보다 적은 값
오른쪽 자식 노드: 부모 보다 큰 값

정렬이 쉬움
올림차순: 왼쪽노드 -> 부모노드 -> 오른쪽노드 ------ 2(왼쪽노드) -> 3(부모노드) -> 5(오른쪽노드)
내림차순: 오른쪽노드 -> 부모노드 -> 왼쪽노드 ------- 9(오른쪽노드) -> 6(부모노드) -> 5(왼쪽노드)-> 3(부모노드)-> 2(왼쪽노드)
범위검색이 쉬움

6미만인 값들 -> 6의 왼쪽의 값들
6 이상의 값들 -> 6 오른쪽의 값들
TreeSet
TreeSet<E> treeSet = new TreeSet<E>();
특징
이진트리(binary tree)를 기반으로 한 Set 컬렉션
왼쪽과 오른쪽 자식노드를 참조하기 위한 두개의 변수로 구성

주요 메소드
특정 객체를 찾는 메소드: first(), list(), lower(), higher(), ...
정렬 메소드: descendingIterator(), descendingSet()
범위 검색 메소드: headSet(), tailSet, subSet()
Exam1
import java.util.Iterator;
import java.util.TreeSet;
public class TreeSetExample1 {
public static void main(String[] args) {
TreeSet<Integer> scores = new TreeSet<>();
scores.add(new Integer(87));
scores.add(new Integer(98));
scores.add(new Integer(75));
scores.add(95);
scores.add(80);
Integer score = null;
score = scores.first();
System.out.println("가장 낮은 점수: " + score);
score = scores.last();
System.out.println("가장 높은 점수: " + score + "\n");
score = scores.lower(95);
System.out.println("95점 아래 점수: " + score);
score = scores.higher(95);
System.out.println("95점 위의 점수: " + score);
score = scores.floor(new Integer(95));
System.out.println("95점 이거나 바로 아래 점수: " + score);
score = scores.ceiling(new Integer(85));
System.out.println("85점 이거나 바로 위의 점수: " + score);
while (!scores.isEmpty()) {
score = scores.pollFirst(); //왼쪽 객체 부터 결과를 가져오고 Set에서 지워버린다. 오름차순
// pollLast(); //오른쪽 객체부터 결과를 가져옴. 내림차순
System.out.println(score + "(남은 객체 수: " + scores.size() + ")");
}
Iterator<Integer> integerIterator = scores.iterator();
while (integerIterator.hasNext()) {
int s = integerIterator.next(); //결과를 가져오기만한다.
integerIterator.remove(); // 결과를 지운다.
System.out.println(s + "(남은 객체 수: " + scores.size() + ")");
}
}
}
// 결과값
가장 낮은 점수: 75
가장 높은 점수: 98
95점 아래 점수: 87
95점 위의 점수: 98
95점 이거나 바로 아래 점수: 95
85점 이거나 바로 위의 점수: 87
75(남은 객체 수: 4)
80(남은 객체 수: 3)
87(남은 객체 수: 2)
95(남은 객체 수: 1)
98(남은 객체 수: 0)
Exam2
import java.util.NavigableSet;
import java.util.TreeSet;
public class TreeSetExample2 {
public static void main(String[] args) {
TreeSet<Integer> scores = new TreeSet<>();
scores.add(new Integer(87));
scores.add(new Integer(98));
scores.add(new Integer(75));
scores.add(95);
scores.add(80);
NavigableSet<Integer> descendingSet = scores.descendingSet(); //내림차순으로 저장된 Set을 얻는다.
for (Integer score : descendingSet) {
System.out.print(score + " ");
}
System.out.println();
NavigableSet<Integer> asendingSet = descendingSet.descendingSet(); //내림차순된 것을 뒤바꾼다.
for (Integer score : asendingSet) {
System.out.print(score + " ");
}
}
}
//결과값
98 95 87 80 75
75 80 87 95 98
Exam3
import java.util.NavigableSet;
import java.util.TreeSet;
public class TreeSetExample3 {
public static void main(String[] args) {
TreeSet<String> treeSet = new TreeSet<>();
treeSet.add("apple");
treeSet.add("forever");
treeSet.add("description");
treeSet.add("ever");
treeSet.add("zoo");
treeSet.add("base");
treeSet.add("guess");
treeSet.add("cherry");
System.out.println("[c~f 사이의 단어 검색]");
NavigableSet<String> rangeSet = treeSet.subSet("c", true, "f", true);
for (String word : rangeSet) {
System.out.println("word = " + word);
}
}
}
[c~f 사이의 단어 검색]
word = cherry
word = description
word = ever
TreeMap

특징
이진트리(binary tree) 를 기반으로 Map 컬렉션 키와 값이 저장된 Map.Entry를 저장
왼쪽과 오른쪽 자식노드를 참조하기 위한 두개의 변수로 구성
주요 메소드
단일 노드 객체를 찾는 메소드: firstEntry(), lastEntry(), lowerEntry(), HigherEntry(), ...
정렬 메소드: descendingKeySet(), descendingMap()
범위 검색 메소드: headMap(), tailMap, subMap()
Exam1
import java.util.Map;
import java.util.TreeMap;
public class TreeMapExample1 {
public static void main(String[] args) {
TreeMap<Integer, String> scores = new TreeMap<>();
scores.put(new Integer(87), "김나박");
scores.put(new Integer(98), "김범수");
scores.put(new Integer(75), "나얼");
scores.put(new Integer(95), "박정현");
scores.put(new Integer(80), "김연우");
Map.Entry<Integer,String > entry = null;
entry = scores.firstEntry();
System.out.println("가장 낮은 점수: " + entry.getKey() + "-" + entry.getValue() + "\n");
entry = scores.lastEntry();
System.out.println("가장 높은 점수: " + entry.getKey() + "-" + entry.getValue() + "\n");
entry = scores.lowerEntry(95); //95 아래의 점수
System.out.println("95 아래 점수: " + entry.getKey() + "-" + entry.getValue() + "\n");
entry = scores.higherEntry(95); //95 위의 점수
System.out.println("95 위의 점수: " + entry.getKey() + "-" + entry.getValue() + "\n");
entry = scores.floorEntry(new Integer(95));
System.out.println("95점 이거나 바로 아래 점수: " + entry.getKey() + "-" + entry.getValue() + "\n");
entry = scores.ceilingEntry(new Integer(95));
System.out.println("95점 이거나 바로 위의 점수: " + entry.getKey() + "-" + entry.getValue() + "\n");
while (!scores.isEmpty()) {
entry = scores.pollFirstEntry(); //오름차순
System.out.println(entry.getKey() + "-" + entry.getValue()+ "(남은 객체 수: " + scores.size() + ")");
}
}
}
//결과
가장 낮은 점수: 75-나얼
가장 높은 점수: 98-김범수
95 아래 점수: 87-김나박
95 위의 점수: 98-김범수
95점 이거나 바로 아래 점수: 95-박정현
95점 이거나 바로 위의 점수: 95-박정현
75-나얼(남은 객체 수: 4)
80-김연우(남은 객체 수: 3)
87-김나박(남은 객체 수: 2)
95-박정현(남은 객체 수: 1)
98-김범수(남은 객체 수: 0)
Exam2
import java.util.Map;
import java.util.NavigableMap;
import java.util.Set;
import java.util.TreeMap;
public class TreeMapExample2 {
public static void main(String[] args) {
TreeMap<Integer, String> scores = new TreeMap<>();
scores.put(new Integer(87), "김나박");
scores.put(new Integer(98), "김범수");
scores.put(new Integer(75), "나얼");
scores.put(new Integer(95), "박정현");
scores.put(new Integer(80), "김연우");
NavigableMap<Integer, String> descendingMap = scores.descendingMap();
Set<Map.Entry<Integer, String>> descendingEntrySet = descendingMap.entrySet();
for (Map.Entry<Integer, String> entry : descendingEntrySet) {
System.out.print(entry.getKey() + "-" + entry.getValue() + " ");
}
System.out.println();
// 위의 descendingMap을 다시 descendingMap() 실행 결과
NavigableMap<Integer, String> ascendingMap = descendingMap.descendingMap();
Set<Map.Entry<Integer, String>> ascendingEntrySet = ascendingMap.entrySet();
for (Map.Entry<Integer, String> entry : ascendingEntrySet) {
System.out.print(entry.getKey() + "-" + entry.getValue() + " ");
}
System.out.println();
}
}
//결과
98-김범수 95-박정현 87-김나박 80-김연우 75-나얼
75-나얼 80-김연우 87-김나박 95-박정현 98-김범수
Exam3
import java.util.Map;
import java.util.NavigableMap;
import java.util.TreeMap;
public class TreeMapExample3 {
public static void main(String[] args) {
TreeMap<String, Integer> treeMap = new TreeMap<>();
treeMap.put("apple", new Integer(10));
treeMap.put("forever", new Integer(60));
treeMap.put("description", new Integer(40));
treeMap.put("ever", new Integer(50));
treeMap.put("zoo", new Integer(10));
treeMap.put("base", new Integer(20));
treeMap.put("guess", new Integer(70));
treeMap.put("cherry", new Integer(30));
System.out.println("[c~f 사이의 단어 검색]");
NavigableMap<String, Integer> rangeMap = treeMap.subMap("c", true, "f", true);
for (Map.Entry<String, Integer> entry : rangeMap.entrySet()) {
System.out.println(entry.getKey() + "-" + entry.getValue() + "페이지");
}
}
}
결과
[c~f 사이의 단어 검색]
cherry-30페이지
description-40페이지
ever-50페이지
Comparable과 Comparator
TreeSet과 TreeMap의 자동정렬
TreeSet의 객체와 TreeMap의 키는 저장과 동시에 자동으로 오름차순으로 정렬
숫자(Integer, Double) 타입일 경우에는 값으로 정렬
문자열(String)타입일 경우에는 유니코드로 정렬
TreeSet과 TreeMap은 정렬을 위해 java.lang.Comparable을 구현한 객체를 요구
Integer, Double, String 모두 Comparable 인터페이스를 구현한 클래스
Comparable을 구현하고 있지 않은 경우에는 저장하는 순간 ClassCastException이 발생
사용자 정의 객체를 정렬하고 싶을 경우
방법1: 사용자 정의 클래스가 Comparable을 구현
리턴타입 |
메소드 |
설명 |
int |
compareTo( T o ) |
주어진 객체와 같으면 0을 리턴 주어진 객체보다 적으면 음수를 리턴 주어진 객체보다 크면 양수를 리턴 |
방법2: TreeSet, TreeMap 생성시 Comparator 구현 객체 제공
리턴타입 |
메소드 |
설명 |
int |
compare( T o1, T o2) |
o1 과 o2 가 동등하다면 0을 리턴 o1 이 o2 보다 앞에 오게 하려면 음수를 리턴 o1 이 o2 보다 뒤에 오게 하려면 양수를 리턴 |
Exam1
public class Person implements Comparable<Person>{
public String name;
public int age;
public Person(String name, int age) {
this.name = name;
this.age = age;
}
@Override
public int compareTo(Person o) {
if (age<o.age) return -1;
else if (age == o.age) return 0;
else return 1;
}
}
import java.util.Iterator;
import java.util.TreeSet;
public class ComparableExample {
public static void main(String[] args) {
TreeSet<Person> treeSet = new TreeSet<>();
treeSet.add(new Person("김나박", 45));
treeSet.add(new Person("나얼", 25));
treeSet.add(new Person("박효신", 31));
Iterator<Person> iterator = treeSet.iterator();
while (iterator.hasNext()) {
Person person = iterator.next();
System.out.println(person.name + ": " + person.age);
}
}
}
결과
나얼: 25
박효신: 31
김나박: 45
Exam2
public class Fruit {
public String name;
public int price;
public Fruit(String name, int price) {
this.name = name;
this.price = price;
}
}
import java.util.Comparator;
public class DescendingComparator implements Comparator<Fruit> {
@Override //내림차순 정렬
public int compare(Fruit o1, Fruit o2) {
if (o1.price < o2.price) return 1;
else if (o1.price == o2.price) return 0;
else return -1;
}
}
import java.util.Iterator;
import java.util.TreeSet;
public class ComparatorExample {
public static void main(String[] args) {
TreeSet<Fruit> treeSet = new TreeSet<>(new DescendingComparator());
treeSet.add(new Fruit("포도", 3000));
treeSet.add(new Fruit("수박", 10000));
treeSet.add(new Fruit("딸기", 6000));
Iterator<Fruit> iterator = treeSet.iterator();
while (iterator.hasNext()) {
Fruit fruit = iterator.next();
System.out.println(fruit.name + ": " + fruit.price);
}
}
}