Java

[펌] [Collection Framework ] List, Set and Map

_침묵_ 2005. 1. 20. 04:14

Collection(List, Set) 과 Map.. 기억하자 기억하자 다짐하면서 번번히 차이점을 잊어버리곤 한다.

 

이번엔 절대로!! 잊지 않겠다는 신념으로  "Head First 자바" 부록을 참고해서 확실하게 정리해 보았다. -_-+

 

 

1. Collection

사용자 삽입 이미지

Collection 은 여러개의 객체를 하나의 유닛으로 다루기 위한 최상위 인터페이스이다.

 

객체 집합을 하나의 객체로 다루는 방법에 따라서 두가지로 나뉘는데, List 는 객체들이 들어온 순서대로 참조를 유지하기 위한 목적을 가지고 있고 Set 은 중복된 참조를 허용하지 않는 목적을 가진다.

 

 

2. List

사용자 삽입 이미지

Collection 인터페이스를 상속한 List는 객체들이 들어온 순서대로 참조를 관리한다.

 

들어온 순서가 중요하기 때문에 객체들에게 index(색인)을 부여하고 이를 통해서 각각의 객체에 접근한다.

 

List 에서 중요한 것은 객체들의 순서를 관리하는 것이다. 즉, List 는 index 로 순서를 추적하는데에 관심이 있을 뿐, 같은 객체의 참조가 여러번 들어오거나 null 참조가 들어오는 것은 조사하지 않는다.

 

만일 List에 참조가 여러개 존재하지 않아야 하는 상황이라면 List 보다는 Set 계열의 클래스를 이용하는 것이 좋다.

 

 

a. Vector

 

자바 1.0 부터 수많은 개발자들로부터 사랑받아오던 원년 멤버이지만 Collection 프레임워크가 등장하고 나서 List 인터페이스를 구현하면서 Collection 프레임워크로 편입됐다. Vector는 멀티 쓰레드 환경에서도 사용될 수 있도록 객체의 삽입, 삭제 시에 동기화를 보장하도록 되어있다.

 

하지만 Multi Thread 환경이 아니라면 ArrayList 보다 성능이 떨어지므로 Single Thread 에서 접근한다면 ArrayList 를 대신 사용하는 것이 효율적이다.

 

b. ArrayList

 

Collection 을 상속한 클래스들 중에서 add 메소드의 실행이 가장 빠르고 배열의 크기를 자유자재로 늘릴 수 있다. 하지만 Vector 처럼 동기화 과정은 제공하지 않는다. Collection 계열 클래스들은 (Vector를 제외하고) 여러개의 쓰레드가 동시에 접근하는 상황에 대한 대비책은 없기 때문에 주의할 필요가 있다. (이에 관한 추가 사항은 6.Collections 에서 다룬다.)

 

c. LinkedList

 

List 인터페이스의 기본적인 구현 외에도 추가적으로 몇개의 메소드를 넣어서 사용의 편리성을 도모했다. 이 몇개의 메소드란 addFirst(), addLast(), removeFirst(), removeLast() 등이다. LinkedList는 자체로서 사용되기 위해서라기 보다는 스택, 큐 등 사용자가 ADT를 구축할 때 내부에서 사용되기 위한 측면이 강하다.

 

따라서 단순히 객체에 대한 참조를 넣고 빼기 위해서라면 LinkedList 를 쓰기보다는 Vector나 ArrayList 를 사용하는 것이 바람직하다.(쓰더라도 문제될 건 없다.)

 

 

3. Set

사용자 삽입 이미지

List 가 항목의 순서를 관리하는데 비해 Set 는 중복된 항목을 방지하는데 관심이 있다. 이를 위해서 Set 에 의해서 관리되는 객체는 equals() 메소드를 구현해야 한다.

 

자바에서 == 는 단순히 객체의 주소에 근거해서 비교 결과를 반환하기 때문에 equals() 메소드에서 객체의 "내용"을 비교하는 과정을 적어넣아야 Set 에서 equals() 메소드를 통해서 이미 존재하는 항목인지 아닌지를 확인할 수 있다.

 

a. HashSet

 

HashSet 은 가장 빠른 접근을 보장한다. HashSet은 내부적으로 HashMap 을 이용한다. HashSet에 추가되는 항목은 HashMap의 키값으로 저장이 되기 때문에 HashSet이 하는 일이란 HashMap과 사용자 사이의 중계 역할만을 할 뿐이다. 

 

HashSet에서는 항목의 순서를 확인할 수 없다.새로운 객체가 HashSet 에 들어오게 되면 내부에서 객체의 참조 위치가 바뀔 수도 있는데, 이는 HashSet 내부에서 이용하는 HashMap의 특성때문이다.

 

b. LinkedHashSet

 

Set 에 순서를 부여하기 위해서 java 1.4에서 LinkedHashSet 클래스가 등장했다. 이 클래스는 내부에서 double-link 를 이용해서 linked list 를 구현함으로써 원소가 추가된 순서를 유지한다.  LinkedHashSet도 HashSet과 마찬가지로 내부에서 LinkedHashMap 인스턴스를 사용하고 있다.

 

TreeSet 은 Set의 항목들을 정렬된 순서대로 보관한다. 항목을 정렬하기 위해서 TreeSet이 하는 일이란 SortedMap 인스턴스에 작업을 위임하는 것 뿐이다. TreeSet 에 추가되는 항목은 SortedMap 인스턴스의 키값으로 등록이 된다. (키값의 정렬은 Map 인터페이스의 역할이다.)

 

위에서 살펴본대로 Set 계열의 클래스들은 자신의 작업을 Map 계열의 클래스들에게 전적으로 위임하고 있다. Set 에서 중복된 원소를 허용하지 않는 정책은 Map에서 중복된 키값이 존재해서는 안되는 정책이므로, Set에서 삽입되는 원소는 모두 Map 인스턴스에서 키값으로 추가가 된다.

 

이러한 이유 때문에 Set 계열의 클래스들과 Map 계열의 클래스들의 이름이 비슷하게 된 것이 아닌가 싶다.

 

 

 

4. Map

 

사용자 삽입 이미지

 

구조적으로 볼 때 Map 인터페이스는 Collection 인터페이스와 피한방울 섞이지 않은 남남이다.Map 인터페이스는 키와 값을 대응시키기 위해서 사용된다. 여기서 키(key)라 함은 하나의 Map 에 담기는 객체들을 유일하게 식별할 수 있는 객체를 의미하는데, 이는 하나의 Map 내에서 같은 값을 가지는 key 는 존재할 수 없음을 뜻한다.

 

주어진 키에 대응 하는 값을 빠르게 찾기 위한 탐색의 측면에서 Map 계열 클래스들의 의미가 있다고 하겠다.

 

*Collection은 객체들을 넣고 빼는데 있어서 어떻게 이 객체들을 관리할 것인가를 다루고 있고Map은 키를 통해서 실제 객체에 접근한다.*

 

 

5. Collections

 

Collections 클래스는 Collection 인터페이스를 구현한 하위 클래스들에게 다양한 오퍼레이션을 제공할 목적으로모든 메소드가 static 메소드이다. 따라서 모든 Collection 계열의 인스턴스에 대해서 필요에 따라 다양한 작업을 할 수 있다.

 

http://java.sun.com/j2se/1.4.2/docs/api/java/util/Collections.html

 

a. 동기화 지원

 

위에서 언급한 ArrayList 뿐만이 아니라, Collection 을 구현하는 클래스들은 모두 ArrayList 처럼 동기화에 대한 대비책이 없다. 따라서 Vector와 Hashtable 을 제외한 모든 Collection 객체들이 Multi Thread 환경에서 사용되기 위해서는 별도의 기능을 갖춰야 하는데, 이를 위한 메소드가 Collections 클래스에 존재한다.

 

static CollectionsynchronizedCollection(Collection c)
          Returns a synchronized (thread-safe) collection backed by the specified collection.
static ListsynchronizedList(List list)
          Returns a synchronized (thread-safe) list backed by the specified list.
static MapsynchronizedMap(Map m)
          Returns a synchronized (thread-safe) map backed by the specified map.
static SetsynchronizedSet(Set s)
          Returns a synchronized (thread-safe) set backed by the specified set.
static SortedMapsynchronizedSortedMap(SortedMap m)
          Returns a synchronized (thread-safe) sorted map backed by the specified sorted map.
static SortedSetsynchronizedSortedSet(SortedSet s)
          Returns a synchronized (thread-safe) sorted set backed by the specified sorted set.

 

다음과 모든 Collection 계열의 객체에 대해서 synchronized...(..) 메소드로 Multi Thread 환경에서 이용가능하도록 전환할 수 있다. 

 

List list = Collections.synchronizedList(newArrayList(...));

List list = Collections.synchronizedList(newLinkedList(...));

 

SortedSet s = Collections.synchronizedSortedSet(newTreeSet(...));

Set s = Collections.synchronizedSet(newHashSet(...));

Set s = Collections.synchronizedSet(newLinkedHashSet(...));

 

 

Map m = Collections.synchronizedMap(newHashMap(...));

Map m = Collections.synchronizedMap(newTreeMap(...));
Map m = Collections.synchronizedMap(newLinkedHashMap(...));

 

'Java' 카테고리의 다른 글

[펌]자바성능을 향상시키는 코딩  (0) 2005.06.15
자바 스레드 고급 동기화 1  (0) 2005.01.26
[펌] jar파일의 힘  (0) 2005.01.20