자바의 정석

자바에서 제공하는 패키지

핵심 인터페이스 - List, Set, Map

인터페이스 ListSet은 많은 공통 부분이 있어서, 공통된 부분을 다시 뽑아 Collection 인터페이스를 정의할 수 있었다. Map은 전혀 다른 형태로 컬렉션을 다루기 때문에 같은 상속 계층도에 포함되지 못했다.

프로그래밍 실력을 어느 정도 갖추게 되었을 때 컬렉션 프레임웍의 실제 소스를 분석해보면 객체 지향적인 설계능력을 향상시키는데 많은 도움이 될것이다

List, Map, Set의 접미어가 붙어 구분하기 쉽지만 Vector, STack, Hashtable, Properties와 같은 클래스들은 컬렉션 프레임웍이 만들어지기 전부터 존재하던 것이기 때문에 접미어 명명법을 따르지 않는다. 이러한 컬렉션 클래스들은 호환을 위해 설계를 변경해서 남겨두었지만 가능하면 사용하지 않는 것이 좋다. 새로 추가된 ArrayList나 HashMap을 사용하자.

List 인터페이스

List 인터페이스는 중복을 허용하면서 저장 순서가 유지되는 컬렉션을 구현하는데 사용된다.

# Vector와 ArrayList는 배열을 이용한다. 데이터를 읽어오고 저장하는 데는 효율이 좋지만, 용량을 변경해야할 때는 새로운 배열을 생성한 후 기존의 배열로부터 새로 생성된 배열로 복사해야하기 때문에 상당히 효율이 떨어진다는 단점을 가지고 있다.

LinkedList

배열은 가장 기본적인 형태의 자료구조로 간단하며 사용하기 쉽고 데이터를 읽어 오는 시간 access time이 가장 빠르다는 장점이 있지만 다음과 같은 단점도 있다.

배열은 모든 데이터가 연속적으로 존재하지만 LinkedList는 불연속적으로 존재하는 데이터를 서로 연결(link)한 형태로 구성되어 있다.

LinkedList는 이동방향이 단방향이기 때문에 이전 요소에 대한 접근이 어렵다. 따라서 Node에 참조 변수 하나만 더 추가하여 이전 요소에 대한 참조가 가능하도록 한 Doubly Llinked List가 있다. Doubly Linked List는 Linked List 보다 각 요소에 대한 접근과 이동이 쉽기 때문에 Linked List 보다 더 많이 사용 된다.

Doubly Linked List 보다 접근성을 향상시킨 것이 Doubly Circular Linked List(이중 원형 연결리스트) 인데, 단순히 첫번째 node와 마지막 node를 연결시킨 것이다. 이렇게 하면 마지막 node의 다음은 첫번째 node가 되고, 첫번째 node의 이전 node는 마지막 node가 된다.

LinkedList 역시 List 인터페이스를 구현했기 때문에 ArrayList와 내부 구현방법만 다를 뿐 제공하는 메서드와 종류와 기능은 거의 같다.

또는 두 클래스의 정점을 이용해서 두 클래스를 혼합해서 사용하는 방법도 생각해 볼 수 있다. 처음에 작업하기 전에 데이터를 저장할 때는 ArrayList를 사용한 다음, 작업할 때는 LinkedList로 데이터를 옮겨서 작업하면 좋은 효율을 얻을 수 있을 것이다.

ArrayList arrayList = new ArrayList(1000000);
for(int i=0; i<1000000; i++) arrayList.add(i);

LinkedList linkedList = new LinkedList(arrayList);

위처럼 컬렉션 프레임웍에 속한 대부분의 컬렉션 클래스들은 이처럼 서로 변환이 가능한 생성자를 제공하므로 이를 이용하면 간단히 다른 컬렉션 클래스로 데이터를 옮길 수 있다.

Stack과 Queue

그렇다면 스택과 큐를 구현하기 위해서는 어떤 컬렉션 클래스를 사용하는게 좋을까? 스택은 배열기반의 ArrayList가 적합, 큐는 LinkedList이 더 적합

Stack은 컬렉션 프레임웍 이전부터 존재하던 것이기 때문에 ArrayList가 아닌 Vector로부터 상속받아 구현.

1.6 Enumeration, Iterator, ListIterator

1.7 HashSet

HashSet은 Set 인터페이스를 구현한 가장 대표적인 컬렉션이며, Set 인터페이스의 특징처럼 중복을 허용하지 않는다.

HashSet은 저장순서를 유지하지 않으므로 저장순서를 유지하고자 한다면 LinkedHashSet을 사용해야 한다.