검색 기능을 강화시킨 컬렉션

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);
}
}
}


Set  컬렉션의 특징 및 주요 메소드

 특징

수학의 집합에 비유될 수 있다.

저장 순서가 유지되지 않는다.

객체를 중복해서 저장할 수 없고, 하나의   null만 저장할 수 있다.

구현 클래스

HashSet,    LinkedHashSet,    TreeSet

주요 메소드

기능 

메소드 

설명 

객체

 추가 

  boolean add(E e) 

  주어진 객체를 저장, 객체가 성공적으로 저장되면
  true를 리턴하고 중복 객체면 fasle 를 리턴 

객체

 검색

  boolean contains(Object o) 

  주어진 객체가 저장되어 있는지 여부 

  isEmpty() 

  컬렉션이 비어 있는지 조사 

  Iterator<E> iterator() 

  저장된 객체를 한번씩 가져오는 반복자 리턴 

  int size() 

  저장되어 있는 전체 객체수 리턴 

객체

 삭제 

  void clear() 

  저장된 모든 객체를 삭제 

  boolean remove(Object o )

  주어진 객체를 삭제 



객체 추가 및 삭제

Set<String> set = ...;
set.add("홍길동");          객체추가
set.add("김나박");            객체 추가
set.remove("홍길동");     객체 삭제

Set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드가 없다.

대신, 전체 객체를 대상으로 한번씩 반복해서 가져오는 반복자(Iterator)를 제공한다.

Set<String> set  = ...;

Iterator<String> iterator = set.iterator();


리턴타입 

메소드명 

설명 

boolean 

  hasNext() 

  가져올 객체가 있으면 true를 반환하고 없으면  false를 반환한다. 

 E

  next() 

   컬렉션에서 하나의 객체를 가져온다.

void 

  remove() 

  Set 컬렉션에서 객체를 제거한다. 



Set<String> set = ...;

Iterator<String> iterator = set.iterator();                                                                    

while(iterator.hasNext()){

//String 객체를 하나 가져옴

String str= iterator.next();

}   저장된 객체 수 만큼 루핑한다. 

    == 

Set<String set = ...;


for(String str : set) {



반복자를 통한 객체 제거

while(iterator.hasNext()){

String str= iterator.next();

if(str.equals("홍길동")){

iterator.remove();

}

}




HashSet

특징

동일 객체 및 동등 객체는 중복 저장하지 않는다.

동등 객체 판단 방법


Exam1

import java.util.HashSet;
import java.util.Iterator;
import java.util.Set;

public class HashSetExample1 {
public static void main(String[] args) {
Set<String> set = new HashSet<>();

set.add("Java");
set.add("JDBC");
set.add("Servlet/JSP");
set.add("Java"); //같은 객체이기 떄문에 저장이 안됨
set.add("iBATIS");

int size = set.size();
System.out.println("총 객체수: " + size);

Iterator<String> iterator = set.iterator();
while (iterator.hasNext()) {
String element = iterator.next();
System.out.println("\t" + element);
}

set.remove("JDBC");
set.remove("iBATIS");

System.out.println("총 객체수: " + set.size());

for (String element : set) {
System.out.println("\t" + element);
}

set.clear();
if (set.isEmpty()) {
System.out.println("비어 있습니다.");
} else {
System.out.println("비어 있지 않습니다.");
}
}
} 결과 총 객체수: 4 Java JDBC Servlet/JSP iBATIS 총 객체수: 2 Java Servlet/JSP 비어 있습니다.

Exam2

public class Member {
public String name;
public int age;

public Member(String name, int age) {
this.name = name;
this.age = age;
}

@Override
public boolean equals(Object obj) {
if (obj instanceof Member) {
Member member = (Member) obj;
return member.name.equals(name) && member.age == age;
} else {
return false;
}
}

@Override
public int hashCode() {
return name.hashCode() + age;
}
}
import java.util.HashSet;
import java.util.Set;

public class HashSetExample2 {
public static void main(String[] args) {
Set<Member> set = new HashSet<>();

set.add(new Member("김나박", 30));
set.add(new Member("김나박", 30));
// Member클래스의  hashCode()와 equals()를 재정의해서 동등한객체를 만들어 줌으로써
// 동등한 객체.. 때문에 1개의 객체만 저장이됨

System.out.println("총 객체수" + set.size());
}
} //결과 총 객체수1


+ Recent posts