6.4 컬렉션과 맵

JAVA PROGRAMMING/JAVA 2010/02/21 21:24 by 킨테리 KinTeL



6.4.1 배열의 발전된 형태



배열은 고전적인 개념을 그대로 사용하고 있지만, 배열도 발전을 거듭하고 있습니다. C++의 보다 발전된 형태인 자바에서 배열 대신 사용하는 요소는 없을까요? 물론 있습니다. 이것이 바로 컬렉션(Collection)과 맵(Map) 계열의 클래스입니다.

배열의 크기를 동적으로 늘릴 수 없다는 단점을 보완해서, 동적으로 필요할 때 메모리를 확장할 수 있는 클래스가 컬렉션과 맵 계열의 클래스입니다. 사람들은 데이터의 보관이라는 측면에서 한정된 크기보다는 보다 다이나믹한 것을 좋아합니다. 데이터를 집어넣으면 알아서 메모리의 크기가 커지고, 삭제하면 알아서 작아지는 데이터의 보관법은 당연히 더 편리합니다. 어떻게 보면 배열은 프로그래머가 사용할 크기를 미리 지정한 후 사용하는 비효율적인 저장공간일 수도 있습니다. 이러한 저장공간에 여러 가지 자료구조적인 기능이 가미된 저장공간으로서 컬렉션과 맵류의 클래스들이 있습니다. 

▣ Collection류와 Map류의 클래스
◈ 자료구조적인 기능의 클래스

사실 Collection과 Map은 java.util 패키지에 있는 인터페이스입니다. 대부분의 자료구조를 지원하는 클래스들이 이들 인터페이스를 구현하고 있기 때문에 컬렉션류 또는 맵류라고 부르는 것입니다. Collection과 Map 인터페이스가 어떠한 기능을 가진 인터페이스인지 이 절에서 알아보기로 하죠.

▣ Collection과 Map 인터페이스
◈ Collection과 Map은 인터페이스이기 때문에 메서드의 프로토타입만 존재한다.
◈ Collection을 구현해서 사용하면 집합적인 저장공간으로서의 기능을 구현한 클래스가 된다.
◈ Map을 구현해서 사용하면 검색적인 저장공간으로서의 기능을 구현한 클래스가 된다.

이들 인터페이스 내에 포함되어진 추상 메서드를 어떻게 구현하느냐에 따라 그 기능이 달라집니다. 일반적으로 Collection 인터페이스는 집합적인 데이터를 관리하기 위해서 사용하며, Map 인터페이스는 검색적인 저장공간을 지원하기 위해서 사용하는 경우가 많습니다.

Collection류를 대표하는 Vector 클래스와 Map류를 대표하는 Hashtable을 학습하면서 Collection과 Map의 개념에 접근하도록 하겠습니다.



6.4.2 Collection & Map



Collection은 Stack, Vector, LinkedList, TreeSet, HashSet과 같은 클래스들이 사용하는 인터페이스입니다. Collection은 집합적인 저장공간으로서의 기능을 가지고 있으며, 이것을 구현한 클래스들은 모두 집합적인 객체의 저장공간으로서의 역할을 할 수 있습니다. 객체의 묶음이지만 단순한 집합이냐, 순서가 있는 집합이냐에 따라서 약간 다르게 구현되어집니다. 

Collection은 객체의 저장소 역할을 하기 위한 많은 추상 메서드를 포함하고 있습니다. Collection 인터페이스의 추상 메서드 중 데이터를 삽입하는 메서드와 제거하는 메서드는 다음과 같습니다.

◈ boolean add(Object o); //객체를 삽입하는 메서드
◈ boolean remove(Object o); //특정 객체를 삭제하는 메서드

그리고 객체 저장소 내에 특정 데이터가 있는지 없는지, 비어 있는지, 몇 개나 있는 지를 알아내기 위한 추상 메서드들은 다음과 같습니다.

◈ boolean isEmpty(); //비어 있는지 확인하는 메서드
◈ boolean contains(Object o); //특정 객체가 포함되어 있는지 확인하는 메서드
◈ int size(); //포함된 객체의 수를 리턴하는 메서드
 
모든 요소들을 배열 형태로 리턴하는 toArray()라는 메서드도 포함하고 있습니다.

◈ Object[] toArray(); //포함된 모든 객체들을 배열 형태로 리턴하는 메서드

Collection 인터페이스 내에는 이 이외에도 몇 개의 추상 메서드들이 더 있습니다. Java Doc API를 확인해 보시기 바랍니다. Collection은 인터페이스이기 때문에 내부의 메서드들이 구현된 상태가 아닙니다. Collection 인터페이스를 구현한 많은 클래스들이 있으니, 여러분들은 Collection 인터페이스가 구현되었는지 확인한 후에 이 기능들을 사용하시면 됩니다. 

▣ Collection 인터페이스를 구현한 클래스
◈ Stack, Vector, LinkedList, TreeSet, HashSet

Collection이라고 해서 대단한 기능을 가지고 있는 것은 아닙니다. 데이터의 삽입, 삭제, 검색 등과 같은 간단한 집합적인 개념의 기능을 가지고 있습니다. Collection 인터페이스를 구현하는 클래스에서는 각각의 기능에 맞게 추상 메서드들을 다시 구현하고 있습니다.

Collection과 달리 Map은 검색적인 개념을 담고 있는 인터페이스입니다. Map으로 구현되어진 클래스는 Attributes, HashMap, Hashtable, TreeMap 등이 있습니다. Map 인터페이스는 검색을 위해서 각각의 데이터에 키(Key)를 함께 보유하게 됩니다. 물론 데이터를 삽입할 때 키(Key)와 데이터(Value)를 함께 주어야 합니다. 그리고 키를 이용해서 데이터를 빠르게 검색할 수도 있습니다.

◈ Object put(Object key, Object value); //데이터를 삽입하는 메서드
◈ Object remove(Object key); //키(key)를 이용해서 데이터를 제거하는 메서드
◈ Object get(Object key); //키(key)를 이용해서 데이터를 검색하는 메서드

Collection에서는 데이터만 삽입하고 추출하지만, Map에서는 키와 데이터를 함께 주는 것이 약간 다릅니다. Map 또한 객체의 저장소 역할을 하기 때문에 데이터를 삽입하고 추출하는 메서드를 제공해 주고 있습니다. Map의 가장 큰 특징은 키를 이용해서 데이터를 제거하거나 데이터를 찾을 수 있다는 것입니다.

Map 인터페이스는 비어 있는지, 특정 키가 있는지, 특정 데이터가 있는지, 데이터가 몇 개인 지를 검사하는 메서드를 지원해 주고 있습니다.

◈ boolean isEmpty(); //비어 있는지
◈ boolean containsKey(Object key); //특정 키가 있는지
◈ boolean containsValue(Object value); //특정 데이터가 있는지
◈ int size(); //포함된 객체가 몇 개인지
 
Collection이나 Map은 객체의 저장공간을 위한 기능적인 측면을 담당한다는 것은 동일합니다. 하지만 Collection은 단순 집합적인 개념의 저장소의 기능을 가지고 있으며, Map은 키를 이용한 검색적인 저장소의 기능을 가지고 있다는 것이 다릅니다. 특별한 기능은 없습니다. 데이터를 삽입하고 필요할 때 꺼집어 낼 수 있으면 그것으로 끝입니다. 키 없이 단순히 데이터만을 넣어두고자 할 때는 Collection 계열을 사용하면 됩니다. 키를 사용해서 데이터를 빠르게 검색하기 위해서는 Map 계열을 사용하면 됩니다. 

Collection의 추상 메서드들은 데이터의 삽입, 삭제, 검색 등 데이터를 메모리상에서 관리하는 메서드들입니다. 이 인터페이스를 구현하였다면 당연히 데이터를 삽입하는 기능을 구현하였을 것입니다. 그리고 데이터의 삭제와 검색 또한 구현하였을 것입니다. 결론적으로 Collection 인터페이스를 구현하였다면 객체를 저장하고, 저장된 객체를 핸들하는 작업을 하게 되는 것입니다. 즉 Collection은 데이터를 넣고 삭제하고 그리고 얻어내는 기능을 하는 인터페이스이며, 이를 구현하는 클래스 중에 가장 대표적인 클래스가 바로 Vector입니다. 

▣ Vector 클래스
◈ Collection을 구현하는 대표적인 클래스는 Vector이다.

Map의 대표적인 클래스는 Hashtable입니다. 개념상의 약간 차이가 있긴 하지만 객체의 저장소 역할을 하는 것은 Collection 유형과 동일합니다. 단지 키를 이용한다는 측면에서 Map이라 부르는 것입니다.

▣ Hashtable 클래스
◈ Map을 구현하는 대표적인 클래스는 Hashtable이다.

보통 Vector나 Hashtable과 같은 클래스는 소형 메모리 데이터베이스의 기능인 삽입, 삭제, 수정, 검색의 기능을 할 수 있습니다. 하지만 데이터를 장기간 보관하는 것이 아니라 프로그램이 실행되는 동안에만 사용하는 간단한 저장소같은 역할을 합니다. 저장공간이라는 의미에 있어서는 배열과 일맥상통합니다. 그리고 Collection 인터페이스는 배열로 쉽게 전환할 수 있는 메서드 또한 포함하고 있습니다.



6.4.3 배열과의 차이



Collection과 Map 유형의 특징은 앞에서도 언급했지만 객체의 삽입, 삭제, 수정, 검색의 기능을 가지고 있습니다. 그리고 Collection과 Map 유형들은 각각의 클래스마다 구현되는 알고리즘이 다를 뿐 전부 같은 부류들입니다. 구현되는 알고리즘이란 LinkedList, Hash, Stack 등과 같은 자료구조 알고리즘을 의미합니다. 이러한 차이점만 있을 뿐이지 별다른 사용상의 차이점은 없습니다.

이들이 배열과 구분되는 가장 큰 특징은 데이터의 크기를 동적으로 확장할 수 있다는 것입니다. 배열은 첨자의 개수 만큼 변수를 생성하고, 그리고 사용할 때 정확하게 첨자의 범위 내에서 사용할 수 있습니다. 만약 배열의 범위를 벗어난다면 ArrayIndexOutOfBoundsException을 발생시킵니다. 하지만 Collection과 Map 유형은 데이터를 삽입할 때 동적으로 메모리를 늘립니다. 이것이 배열과 구분되는 특징입니다. 그리고 배열은 기본 데이터 타입의 데이터와 객체를 그 대상으로 하지만, Collection과 Map 유형은 오직 객체만을 대상으로 합니다. 

▣ Collection과 Map 유형이 배열과 구분되는 점
◈ 동적 메모리 확장
◈ Collection과 Map류는 객체만을 저장의 대상으로 한다.

다음은 Collection과 Map 인터페이스에 선언되어 있는 삽입과 삭제 메서드의 원형입니다. 삽입과 삭제의 대상이 객체인 것을 확인할 수 있습니다.

▣ Collection의 삽입과 삭제를 위한 추상 메서드
◈ boolean add(Object o)  
◈ boolean remove(Object o) 

▣ Map의 삽입과 삭제를 위한 추상 메서드
◈ Object put(Object key, Object value)
◈ Object remove(Object key)  

add() 메서드에서 매개변수의 형이 Object형이라는 것을 확인할 수 있습니다. 모든 클래스의 최상위 클래스인 Object 클래스를 상속받기 때문에 객체라면 어떤 놈이든지 add()나 put()의 매개변수로 이용될 수 있습니다. 이것도 업캐스팅(Upcasting) 기법이죠. 그리고 데이터를 추출할 때에도 Object형으로 얻게 됩니다. 리턴된 Object형의 객체를 사용하려면 원래의 형으로 다운캐스팅을 해주어야 합니다. 

Collection 유형과 관련된 업캐스팅(Upcasting)과 다운캐스팅(Downcasting)에 대한 자세한 내용은 5장의 업캐스팅의 장점 부분을 참고하시기 바랍니다.



6.4.4 Vector 예제 I



Vector 클래스를 이용하는 방법에 대해서 알아보기로 하죠. 먼저 Vector 클래스의 객체를 생성한 후 다음과 같이 객체를 삽입하면 됩니다.

▣ Vector의 생성과 데이터의 삽입
◈ Vector v = new Vector();
◈ v.addElement(new String("망아지"));
◈ v.addElement(new String("송아지"));
◈ v.addElement(new String("강아지"));
◈ v.addElement(new String("병아리"));

▣ Vector 클래스의 특징
◈ 벡터는 순서의 개념을 가지고 있는 저장공간이다.

Vector v에는 4개의 객체가 삽입되어 있습니다. Vector는 순서를 가지고 있으며, 이 순서는 삽입된 순서를 의미합니다. Vector v에 삽입된 객체는 다음과 같은 순서로 되어 있습니다.

벡터에 데이터가 삽입되는 순서【chap06\vectordataindex.bmp】
 



   
Vector에 존재하는 객체를 추출하기 위해서는 다음과 같이 elementAt()을 사용하면 됩니다.

▣ 인덱스를 이용한 Vector의 데이터 추출
◈ String temp0 = (String)v.elementAt(0);
◈ String temp1 = (String)v.elementAt(1);
◈ String temp2 = (String)v.elementAt(2);
◈ String temp3 = (String)v.elementAt(3);

elementAt()은 인덱스에 해당하는 Vector 내부의 객체를 Object형으로 리턴합니다. 이 때 리턴된 객체를 원래의 형으로 복원해서 사용하면 됩니다. 이러한 과정을 프로그램으로 만들어 보면 다음과 같습니다.

『chap06\VectorMain.java』
ⓙ───────────────────────────────────────
/**
Vector 클래스의 기본적인 사용
**/
import java.util.Vector;
public class VectorMain {
   public static void main(String[] args) {
        Vector v = new Vector(); //Vector 객체 생성
        System.out.println("Vector 생성 직후의 size : " + v.size());
        //1. 벡터에 데이터 4개 삽입 
        v.addElement(new String("망아지"));
        v.addElement(new String("송아지"));
        v.addElement(new String("강아지"));
        v.addElement(new String("병아리"));
        System.out.println("Vector에 데이터 삽입 후의 size : " + v.size());
        //2. 벡터의 요소 출력하기
        for(int i=0; i< v.size(); i++){
            //인덱스를 이용한 데이터 추출(다운캐스팅은 필수적)
            String temp = (String)v.elementAt(i);
            System.out.println("Vector v의 " + i + "번째 :"  + temp);
        }
   } //end of main
} //end of VectorMain class
//㉶--------------------------------------------㉳
/***
C:\javasrc\chap06>javac VectorMain.java
C:\javasrc\chap06>java VectorMain
Vector 생성 직후의 size : 0
Vector에 데이터 삽입 후의 size : 4
Vector v의 0번째 :망아지
Vector v의 1번째 :송아지
Vector v의 2번째 :강아지
Vector v의 3번째 :병아리
***/
───────────────────────────────────────ⓑ

일단 Vector 클래스의 객체를 생성한 후 벡터 내에 존재하는 객체의 수를 출력하기 위해서 size()를 이용하고 있습니다.

▣ Vector 객체의 생성
◈ Vector v = new Vector();
◈ System.out.println("Vector 생성 직후의 size : " + v.size());

현재는 Vector v에 삽입된 객체가 없기 때문에 크기는 0이 됩니다. 그리고 Vector v에 String 객체 4개를 삽입하고 있습니다. 데이터를 삽입할 때는 다음과 같이 addElement(Object obj)를 이용하면 됩니다.

▣ Vector v에 데이터 삽입
◈ v.addElement(new String("망아지"));
◈ v.addElement(new String("송아지"));
◈ v.addElement(new String("강아지"));
◈ v.addElement(new String("병아리"));

삽입된 데이터의 내용을 출력하기 위해서 다음과 같이 for문을 이용해서 전체 데이터에 접근하고 있습니다. 이 때 데이터에 접근하는 순서는 데이터가 삽입된 순서입니다.

▣ Vector v에서 인덱스를 이용한 데이터의 추출
◈ for(int i=0; i< v.size(); i++){
◈         String temp = (String)v.elementAt(i); //다운캐스팅은 필수
◈ }

벡터 내에 있는 객체의 수는 size()를 이용해서 얻을 수 있으며, 그 수만큼 elementAt() 메서드를 이용해서 인덱스 순으로 차례대로 데이터를 추출할 수 있습니다. 그리고 추출된 데이터는 Object형이기 때문에 원래의 형으로 형변환을 해주고 있습니다.

위의 예에서 Vector v를 처음 생성했을 때 객체의 수는 0입니다. 그리고 데이터를 4개 삽입했을 때의 개수는 4입니다. 이 단순한 소스는 Vector가 무엇을 하는 것인지 정확하게 보여주고 있습니다.



6.4.4 Vector 예제 I



Vector 클래스를 이용하는 방법에 대해서 알아보기로 하죠. 먼저 Vector 클래스의 객체를 생성한 후 다음과 같이 객체를 삽입하면 됩니다.

▣ Vector의 생성과 데이터의 삽입
◈ Vector v = new Vector();
◈ v.addElement(new String("망아지"));
◈ v.addElement(new String("송아지"));
◈ v.addElement(new String("강아지"));
◈ v.addElement(new String("병아리"));

▣ Vector 클래스의 특징
◈ 벡터는 순서의 개념을 가지고 있는 저장공간이다.

Vector v에는 4개의 객체가 삽입되어 있습니다. Vector는 순서를 가지고 있으며, 이 순서는 삽입된 순서를 의미합니다. Vector v에 삽입된 객체는 다음과 같은 순서로 되어 있습니다.

벡터에 데이터가 삽입되는 순서【chap06\vectordataindex.bmp】


   
Vector에 존재하는 객체를 추출하기 위해서는 다음과 같이 elementAt()을 사용하면 됩니다.

▣ 인덱스를 이용한 Vector의 데이터 추출
◈ String temp0 = (String)v.elementAt(0);
◈ String temp1 = (String)v.elementAt(1);
◈ String temp2 = (String)v.elementAt(2);
◈ String temp3 = (String)v.elementAt(3);

elementAt()은 인덱스에 해당하는 Vector 내부의 객체를 Object형으로 리턴합니다. 이 때 리턴된 객체를 원래의 형으로 복원해서 사용하면 됩니다. 이러한 과정을 프로그램으로 만들어 보면 다음과 같습니다.

『chap06\VectorMain.java』
ⓙ───────────────────────────────────────
/**
Vector 클래스의 기본적인 사용
**/
import java.util.Vector;
public class VectorMain {
   public static void main(String[] args) {
        Vector v = new Vector(); //Vector 객체 생성
        System.out.println("Vector 생성 직후의 size : " + v.size());
        //1. 벡터에 데이터 4개 삽입 
        v.addElement(new String("망아지"));
        v.addElement(new String("송아지"));
        v.addElement(new String("강아지"));
        v.addElement(new String("병아리"));
        System.out.println("Vector에 데이터 삽입 후의 size : " + v.size());
        //2. 벡터의 요소 출력하기
        for(int i=0; i< v.size(); i++){
            //인덱스를 이용한 데이터 추출(다운캐스팅은 필수적)
            String temp = (String)v.elementAt(i);
            System.out.println("Vector v의 " + i + "번째 :"  + temp);
        }
   } //end of main
} //end of VectorMain class
//㉶--------------------------------------------㉳
/***
C:\javasrc\chap06>javac VectorMain.java
C:\javasrc\chap06>java VectorMain
Vector 생성 직후의 size : 0
Vector에 데이터 삽입 후의 size : 4
Vector v의 0번째 :망아지
Vector v의 1번째 :송아지
Vector v의 2번째 :강아지
Vector v의 3번째 :병아리
***/
───────────────────────────────────────ⓑ

일단 Vector 클래스의 객체를 생성한 후 벡터 내에 존재하는 객체의 수를 출력하기 위해서 size()를 이용하고 있습니다.

▣ Vector 객체의 생성
◈ Vector v = new Vector();
◈ System.out.println("Vector 생성 직후의 size : " + v.size());

현재는 Vector v에 삽입된 객체가 없기 때문에 크기는 0이 됩니다. 그리고 Vector v에 String 객체 4개를 삽입하고 있습니다. 데이터를 삽입할 때는 다음과 같이 addElement(Object obj)를 이용하면 됩니다.

▣ Vector v에 데이터 삽입
◈ v.addElement(new String("망아지"));
◈ v.addElement(new String("송아지"));
◈ v.addElement(new String("강아지"));
◈ v.addElement(new String("병아리"));

삽입된 데이터의 내용을 출력하기 위해서 다음과 같이 for문을 이용해서 전체 데이터에 접근하고 있습니다. 이 때 데이터에 접근하는 순서는 데이터가 삽입된 순서입니다.

▣ Vector v에서 인덱스를 이용한 데이터의 추출
◈ for(int i=0; i< v.size(); i++){
◈         String temp = (String)v.elementAt(i); //다운캐스팅은 필수
◈ }

벡터 내에 있는 객체의 수는 size()를 이용해서 얻을 수 있으며, 그 수만큼 elementAt() 메서드를 이용해서 인덱스 순으로 차례대로 데이터를 추출할 수 있습니다. 그리고 추출된 데이터는 Object형이기 때문에 원래의 형으로 형변환을 해주고 있습니다.

위의 예에서 Vector v를 처음 생성했을 때 객체의 수는 0입니다. 그리고 데이터를 4개 삽입했을 때의 개수는 4입니다. 이 단순한 소스는 Vector가 무엇을 하는 것인지 정확하게 보여주고 있습니다.




6.4.6 Hashtable



Vector에서 사용할 수 있는 여러 가지 메서드의 사용 방법을 알아보았습니다. 다음으로 Hashtable의 예를 살펴보도록 하겠습니다. Vector는 데이터(Data)에 해당하는 객체만을 이용했지만, Hashtable은 Map 인터페이스를 구현한 클래스이기 때문에 검색을 위한 키(Key)와 데이터(Data)를 함께 넣어주어야 됩니다. 

▣ Hashtable의 특징
◈ Hashtable에 데이터를 삽입할 때는 키(Key)와 데이터(Data)를 함께 넣어주어야 한다.

다음은 Hashtable을 생성한 후 데이터를 삽입하고 다시 데이터를 추출하는 예입니다.

▣ Hashtable의 사용 예
◈ Hashtable h = new Hashtable(); //객체 생성
◈ h.put("Name", new String("홍길동")); //데이터 삽입
◈ h.put("Age", new Integer(27)); //데이터 삽입
◈ String n = (String)h.get("Name"); //키를 이용한 데이터 추출
◈ String a = (String)h.get("Age"); //키을 이용한 데이터 추출

만약 Vector의 경우에 데이터를 찾고자 한다면 indexOf()나 전체 데이터를 검색하면서 비교해야 합니다. 하지만 Hashtable은 키(Key)만을 이용해서 간단하게 데이터(Data)를 검색할 수 있습니다. Hashtable을 이용하는 예는 다음과 같습니다.

『chap06\HashtableMain.java』
ⓙ───────────────────────────────────────
/**
Hashtable을 테스트하는 예제
**/
import java.util.Hashtable;
public class HashtableMain {
    public static void main(String[] args) {
        Hashtable h = new Hashtable(); //객체 생성
        //Hashtable에 키와 데이터의 삽입
        h.put("Name", new String("홍길동"));
        h.put("Age", new Integer(27));
        h.put("Tel", new String("02-1111-2222"));
        h.put("Handphone", new String("017-777-9999"));
        h.put("Etc", new String("I'm a boy"));
        //키 값을 이용해서 객체 추출
        String name = (String)h.get("Name");
        System.out.println("Name = " + name);
        Integer age = (Integer)h.get("Age");
        System.out.println("Age = " + age.intValue());
   } //end of main
} //end of HashtableMain class
//㉶--------------------------------------------㉳
/***
C:\javasrc\chap06>javac HashtableMain.java
C:\javasrc\chap06>java HashtableMain
Name = 홍길동
Age = 27
***/
───────────────────────────────────────ⓑ

Hashtable은 독특하게 키 값과 데이터를 함께 준 후 키(Key)만으로 데이터(Data)를 추출할 수 있습니다. 일단 제일 먼저 Hashtable 객체를 생성하는 방법은 다음과 같습니다.

▣ Hashtable의 객체 생성
◈ Hashtable h = new Hashtable();

Hashtable h에 키(Key)와 데이터(Data)를 동시에 주면서 5개의 객체를 삽입하고 있습니다. 이 때 삽입하는 원리는 Vector에 데이터를 삽입하는 것과 같이 업캐스팅(Upcasting)의 원리를 이용해서 데이터를 삽입하고 있습니다. 매개변수는 Object형이기 때문에 String형과 Integer형의 객체 모두 put() 메서드의 매개변수로 사용할 수 있습니다.

▣ Hashtable의 데이터 삽입
◈ Hashtable의 put() 메서드의 매개변수가 Object형이기 때문에 형에 관계 없이 데이터를 삽입할 수 있다.

이렇게 생각해 보죠. Hashtable을 만든 사람은 실행 시에 사용자가 어떤 객체를 넣을 것이라고 가정할까요? 모를 일이죠. 즉 실행 시에 어떠한 객체가 입력될지 몰라도 업캐스팅(Upcasting)을 이용하면 모두 받아들일 수 있다는 원리를 이용한 것입니다. 다음은 Hashtable h에 객체를 삽입하는 것을 보여주고 있습니다.

▣ Hashtable h에 키와 데이터 삽입
◈ h.put("Name", new String("홍길동"));
◈ h.put("Age", new Integer(27));
◈ h.put("Tel", new String("02-1111-2222"));
◈ h.put("Handphone", new String("017-777-9999"));
◈ h.put("Etc", new String("I'm a boy"));

그 다음은 키 값을 이용해 객체를 추출한 후 출력하고 있습니다. 데이터가 삽입될 때 Object형으로 형변환되었기 때문에 리턴형은 Object형입니다. 리턴된 객체를 다운캐스팅(Downcasting)해서 다시 원래의 형으로 복원합니다. 다음은 키를 이용해서 Hashtable에 존재하는 객체를 추출하는 예입니다.

▣ Hashtable h에서 키를 이용한 객체 추출
◈ String name = (String)h.get("Name"); //다운캐스팅 필요
◈ Integer age = (Integer)h.get("Age"); //다운캐스팅 필요

지금까지 여러분은 내부적으로 Collection 인터페이스를 사용하는 Vector 클래스와 Map 인터페이스를 사용하는 Hashtable 클래스의 사용법에 대해서 알아보았습니다. 다음 절에서는 열거자(Enumeration)를 이용해서 Hashtable과 Vector를 다루는 방법에 대해서 알아보도록 하겠습니다. 

▣ Hashtable의 특징    
◈ 객체를 삽입할 때 키(Key)와 데이터(Data)를 함께 입력한다.(put() 메서드)
◈ 객체를 추출할 때에는 키(Key)를 이용해서 객체를 추출할 수 있다.(get() 메서드)
◈ Vector는 순서대로 객체가 저장 되지만, Hashtable은 포함된 데이터가 자동으로 소팅된다.



6.4.7 Vector에서의 Enumeration



Vector와 Hashtable을 사용할 때 검색을 용이하게 하기 위한 목적으로 열거자(Enumeration)를 제공해 주고 있습니다. 열거자 인터페이스는 정말 별 것 없습니다. 데이터를 순서대로 추출할 수 있는 메서드 이외에는 전혀 포함하고 있는 것이 없습니다. 사실 메서드도 몇 개 되지 않습니다. 다음은 Enumeration 인터페이스의 원형을 보여주고 있습니다.

▣ Enumeration 인터페이스의 원형
◈ public interface Enumeration{
◈        public boolean hasMoreElements();
◈        public Object nextElement();
◈ }

▣ Enumeration 인터페이스
◈ Vector나 Hashtable의 검색을 위한 도구

Vector나 Hashtable을 이용할 때 약방의 감초처럼 등장하는 것이 이 열거자입니다. Iterator와  Enumeration 인터페이스가 대표적인 열거자입니다.

▣ 대표적인 열거자
◈ Iterator 인터페이스
◈ Enumeration 인터페이스

Iterator와 Enumeration은 똑같은 역할을 하는 인터페이스입니다. 하지만 Enumeration의 이름이 길다는 문제점 때문에 Iterator를 J2SE 1.2버전에서 추가했다고 합니다. 그런데 보통의 프로그래머들은 1.0 버전에서 사용하던 Enumeration를 더 많이 사용하는 것 같습니다. 여하튼 두 인터페이스는 똑같은 역할을 합니다.

Iterator와 Enumeration은 인터페이스이기 때문에 스스로는 객체를 생성할 수 없습니다. 물론 여러분이 직업 구현해서 사용한다면 어쩔 수 없겠지만, 보통의 경우에는 Vector나 Hashtable의 객체로부터 Iterator와 Enumeration을 리턴받는 형식으로 사용합니다. 

▣ Vector의 elements()
◈ Vector 객체로부터 Enumeration을 얻어내는 메서드

Enumeration은 전체 Vector에 있는 데이터를 검색할 수 있게 도와주는 대리자입니다. 제일 먼저 Vector에서 Enumeration 작업을 하기 위해서는 다음과 같이 Enumeration을 얻어야 합니다.

▣ Vector로부터 Enumeration 얻어내기
◈ Vector v = new Vector();
◈ //v에 데이터 삽입
◈ //v에 데이터 삽입
◈ Enumeration enum = v.elements();

Vector의 elements()를 이용해서 Enumeration을 얻었다면, Enumeration에서 사용할 수 있는 메서드는 두 개밖에 없습니다. hasMoreElements()를 이용해서 다음 위치에 데이터가 있는지 확인한 후 nextElement()를 이용해서 다음 위치에 존재하는 데이터를 리턴받으면 됩니다.

▣ Enumeration 사용하기
◈ while(enum.hasMoreElements()){
◈         Object obj = enum.nextElement();
◈ }

Enumeration으로 작업을 할 때 첫 번째 위치는 데이터 앞쪽에 있다고 생각해야 합니다. 즉 어떠한 데이터도 가리키지 않고 있는 상태입니다. 다음의 그림에서와 같이 Enumeration의 첫 번째 위치는 데이터가 존재하지 않는 제일 앞쪽에 위치하고 있습니다.

Enumeration의 커서를 움직이는 방법【chap06\enumerationkey.bmp】
 
   


그리고 hasMoreElement()로 데이터가 있는지 확인한 후 nextElement()를 호출해서 해당 테이터를 리턴받으면서 위치를 한칸 이동하게 됩니다. 이러한 방식으로 모든 데이터를 검색할 수 있습니다. Enumeration의 사용 방법은 다음 예제에서 확인할 수 있습니다. 먼저 Vector에서 Enumeration을 사용하는 예를 살펴보죠.

『chap06\EnumVectorMain.java』
ⓙ───────────────────────────────────────
/**
Vector에서 Enumeration을 테스트하는 예
**/
import java.util.*;
public class EnumVectorMain {
    public static void main(String[] args) {
        Vector v = new Vector(); //객체 생성
        //vector에 데이터 4개 삽입 
        v.addElement(new String("망아지"));
        v.addElement(new String("송아지"));
        v.addElement(new String("강아지"));
        v.addElement(new String("병아리"));
        //Enumeration을 이용한 데이터 출력
        Enumeration enum = v.elements(); //Vector에서 Enumeration 얻기
        while(enum.hasMoreElements()){ //Vector에 데이터가 존재하는지 검사
            //Vector에서 데이터 추출(다운캐스팅 필요)
            String temp = (String)enum.nextElement();
            System.out.println(temp);
        }
    } //end of main
} //end of EnumVectorMain class
//㉶--------------------------------------------㉳
/***
C:\javasrc\chap06>javac EnumVectorMain.java
C:\javasrc\chap06>java EnumVectorMain
망아지
송아지
강아지
병아리
***/
───────────────────────────────────────ⓑ

Enumeration에서 제공하는 2개의 메서드에 대한 사용법은 아주 쉽습니다. 데이터가 존재하는지 확인한 후 데이터의 위치를 이동시키는 개념만 가지고 있다면 모든 데이터를 검색할 수 있습니다. 그리고 nextElement()를 사용할 때 내부에서 리턴되는 데이터의 형이 Object형이기 때문에 적절한 데이터 타입으로 다운캐스팅(Downcasting)한 후에 사용해야 한다는 것도 기억하시기 바랍니다.



6.4.8 Hashtable에서의 Enumeration



다음으로 Hashtable에서 Enumeration을 사용하는 방법을 알아보죠. Hashtable 또한 elements()를 이용해서 Enumeration을 추출할 수 있습니다.

▣ Hashtable에서 Enumeration 얻어내기
◈ Hashtable h = new Hashtable();
◈ //h에 데이터 삽입
◈ //h에 데이터 삽입
◈ Enumeration enum = h.elements();

Hashtable에는 키와 데이터 두 종류가 존재하기 때문에 두 개의 Enumeration을 얻을 수 있습니다. elements()를 사용할 때 Enumeration으로 리턴되는 것은 데이터(Data)에 해당하는 부분입니다. 만약 키(Key)에 해당하는 부분의 Enumeration을 얻고자 한다면 다음과 같이 keys() 메서드를 사용하면 됩니다.

▣ Hashtable의 키(Key)에 해당하는 Enumeration
◈ Enumeration enum2 = h.keys ();

▣ Hashtable의 데이터(Data)에 해당하는 Enumeration
◈ Enumeration enum = h.elements();

Enumeration을 얻었다면 다음과 같이 while문으로 모든 데이터를 검색하면 됩니다.

▣ Enumeration 사용하기
◈ while(enum.hasMoreElements()){
◈         Object obj = enum.nextElement();
◈ }

Hashtable에서 Enumeration을 사용하는 예제는 다음과 같습니다.

『chap06\EnumHashtableMain.java』
ⓙ───────────────────────────────────────
/**
Hashtable에서 Enumeration을 테스트하는 예
**/
import java.util.*;
public class EnumHashtableMain {
    public static void main(String[] args) {
        Hashtable h = new Hashtable();
        //hashtable에 객체의 삽입    
        h.put("1", new String("홍길동"));
        h.put("2", new String("안녕하세요"));
        h.put("3", new String("02-1111-2222"));
        h.put("4", new String("017-777-9999"));
        //Enumeration을 이용한 데이터 출력
        Enumeration enum = h.elements(); //Enumeration 얻기
        while(enum.hasMoreElements()){ //데이터 존재 여부 확인
            //데이터 얻기(다운캐스팅 필요)
            String temp = (String)enum.nextElement(); 
            System.out.println(temp);
        }
    } //end of main
} //end of EnumHashtableMain class
//㉶--------------------------------------------㉳
/***
C:\javasrc\chap06>javac EnumHashtableMain.java
C:\javasrc\chap06>java EnumHashtableMain
017-777-9999
02-1111-2222
안녕하세요
홍길동
***/
───────────────────────────────────────ⓑ

위의 예제는 데이터에 해당하는 부분만 출력하고 있습니다. 여러분들이 직접 keys()를 사용해서 키에 해당하는 Enumeration을 받은 후 데이터를 출력해 보시기 바랍니다.



6.4.9 Iterator



Enumeration과 동일한 기능을 하는 인터페이스가 Iterator입니다. Iterator 역시 열거자에 해당합니다. Enumeration의 hasMoreElements()는 hasNext()라는 메서드로 대체되었으며, nextElement()는 next()로 대체되었습니다. 그리고 Iterator를 얻기 위해서 iterator() 메서드를 사용하면 됩니다.

▣ Iterator의 메서드
◈ hasNext(); //데이터가 있는지 확인
◈ next(); //데이터를 얻어내면서 다음 위치로 이동

▣ Enumeration과 Iterator의 메서드 비교
◈ hasMoreElements() -> hasNext()
◈ nextElement() -> next()

Vector와 Hashtable에서 Iterator를 얻는 방법은 다음과 같습니다.

▣ Vector에서 iterator() 얻기
◈ Vector v = new Vector();
◈ //v에 객체 삽입
◈ Iterator iter = v.iterator();

▣ Hashtable에서 iterator() 얻기
◈ Hashtable h = new Hashtable();
◈ //h에 객체 삽입
◈ Iterator iter2 = h.values().iterator();

Iterator를 얻었다면 Enumeration에서와 같이 while문으로 전체 데이터를 검색하면 됩니다.

◈ while(iter.hasNext()){
◈        Object obj  = iter.next();
◈ }

방법상에 있어서 Enumeration과 Iterator는 비슷한 면을 보이고 있습니다. 과거에는 Enumeration을 많이 선호하는 추세였지만 현재에는 Iterator도 많이 사용됩니다. 다음은 Vector와 Hashtable에서 Iterator를 테스트하는 예입니다.

『chap06\IteratorMain.java』
ⓙ───────────────────────────────────────
/**
Vector와 Hashtable에서 Iterator를 테스트하는 예제
**/
import java.util.*;
public class IteratorMain {
    public static void main(String[] args) {
        Vector v = new Vector();
        //Vector에 객체 삽입
        v.addElement(new String("망아지"));
        v.addElement(new String("송아지"));
        v.addElement(new String("강아지"));
        v.addElement(new String("병아리"));
        //Iterator를 이용한 데이터 출력
        Iterator iter = v.iterator();
        while(iter.hasNext()){
            String temp = (String)iter.next();
            System.out.println(temp);
        }
        System.out.println();

        Hashtable h = new Hashtable();
        //Hashtable에 객체 삽입    
        h.put("1", new String("홍길동"));
        h.put("2", new String("안녕하세요"));
        h.put("3", new String("02-1111-2222"));
        h.put("4", new String("017-777-9999"));
        //Iterator를 이용한 데이터 출력
        Iterator iter2 = h.values().iterator();
        while(iter2.hasNext()){
            String temp = (String)iter2.next();
            System.out.println(temp);
        }
    } //end of main
} //end of IteratorMain class
//㉶--------------------------------------------㉳
/***
C:\javasrc\chap06>javac IteratorMain.java
C:\javasrc\chap06>java IteratorMain
망아지
송아지
강아지
병아리

017-777-9999
02-1111-2222
안녕하세요
홍길동
***/
───────────────────────────────────────ⓑ

Iterator를 이용해서 데이터를 추출하기 위해서 next()를 호출할 때 그 결과로 Object형을 리턴하고 있습니다. 그렇기 때문에 적절한 형으로 다운캐스팅해서 사용하는 것 또한 Enumeration과 동일합니다.
저작자 표시 비영리 변경 금지

'JAVA PROGRAMMING > JAVA' 카테고리의 다른 글

7.2 Exception  (0) 2010/02/21
7.1 Exception  (0) 2010/02/21
6.4 컬렉션과 맵  (0) 2010/02/21
6.3 배열의 참조  (0) 2010/02/21
6.2 배열  (0) 2010/02/21
6.1 Array, Collection, Map  (0) 2010/02/21
1  ... 52 53 54 55 56 57 58 59 60  ... 159 
BLOG main image
(주)KinTeL 회장 김형기

카테고리

분류 전체보기 (159)
My Name Is KinTeL (3)
농구 인생 (1)
사진 이야기 (13)
미디어 (5)
JAVA PROGRAMMING (105)
C# Programming (2)
FLEX (6)
Database (4)
About Eclipse (1)
참조 - Reference (9)
모든 무료 정보 (2)
좋은글 (2)


Statistics Graph
Total : 73,500
Today : 11
Yesterday : 43

최근에 받은 트랙백