java.util
에는 여러 자료구조들을 구현하여 객체를 조작할 수 있는 클래스와 인터페이스들을 포함하고 있습니다.
여기서 여러 데이터들의 집합(그룹)을 컬렉션(Collection)
이라고 부르고, 이들을 쉽게 조작할 수 있도록 표준화 시킨 것을 프레임워크(Framework)
라고 부르기에 이들을 총칭하여 여러 데이터들을 표준화된 조작으로 다룰 수 있게 만들어 놓은 클래스(와 인터페이스)들의 모임을 컬렉션 프레임워크
라고 부르고 있습니다.
정리하자면 여러 데이터 묶음(컬렉션)을 표준화된 사용 방법으로 다룰 수 있게 만들어 놓은 클래스 모음이라고 할 수 있습니다.
컬렉션 프레임워크
는 컬렉션을 크게 List, Set, Map
3가지의 그룹으로 나눕니다.
이렇게 나눈 세 가지 컬렉션을 인터페이스로 만들어서 각 자료구조가 특성에 맞게 구현되어 클래스로 존재하고 있습니다. 이 중 List
와 Set
은 공통적인 부분이 있기에 이 부분을 Collection
이라는 공통 인터페이스를 만들어서 사용하고 있습니다. Map
은 조금 독자적인 성격을 가지고 있어서 따로 분류해서 사용하고 있습니다.
각 인터페이스의 특징과 구현 컬렉션은 다음과 같습니다. 각 컬렉션의 특징을 잘 알아두고 적재적소에 컬렉션을 이용해야합니다.
컬렉션 인터페이스 | 특징 | 구현 컬렉션 |
---|---|---|
List | 순서가 있는 데이터 집합, 데이터 중복 허용 | ArrayList, LinkedList, Vector, Stack 등 |
Set | 순서가 없는 데이터 집합, 데이터 중복 허용하지 않음 | HashSet, TreeSet 등 |
Map | 키-값(key-value) 쌍의 데이터 집합, 순서가 변할 수 있음, 키는 중복 불가능하고 값은 중복 가능 | HashMap, TreeMap, Hashtable, Properties 등 |
Collection 인터페이스
는 List, Set 컬렉션
에서 데이터를 추가, 삭제, 읽기와 같은 기본적인 동작 사항을 정의한 인터페이스입니다.
다음표는 Collection 인터페이스
의 주요 메소드들입니다. 전체적인 내용은 공식 문서에서 확인하실 수 있습니다.
아래 표의 boolean 반환타입 메소드는 성공 여부를 반환합니다.
ex) add에서 결과가 true면 컬렉션 추가 성공, false면 추가 실패
메소드 | 설명 |
---|---|
boolean add(Object o) | 객체를 컬렉션에 추가 |
bolean addAll(Collection c) | 컬렉션의 객체를 모두 컬렉션에 추가 |
void clear() | 컬렉션의 모든 객체 삭제 |
boolean contains(Object o) | 지정된 객체 o가 컬렉션에 있는지 확인 |
boolean containsAll(Collection c) | 지정된 컬렉션 c의 객체들이 컬렉션에 있는지 확인 |
boolean equals(Object o) | 동일 컬렉션인지 비교 |
int hashCode() | 컬렉션의 hashcode 반환 |
boolean isEmpty() | 컬렉션이 비어있는지 확인 |
Iterator iterator() | 컬렉션의 iterator(반복자) 취득 |
boolean remove(Object o) | 컬렉션에서 지정된 객체 o 삭제 |
boolean removeAll(Collection c) | 지정된 컬렉션 c의 객체들을 찾아서 삭제 |
default boolean removeIf(Predicate<? super E> filter) | 조건에 따라 부합하는 객체 삭제 |
boolean retain(Collection c) | 지정된 컬렉션에 존재하는 객체들만 남기고 나머지 객체 삭제 |
int size() | 컬렉션의 크기(컬렉션에 존재하는 객체 수) 반환 |
Object[] toArray() | 컬렉션의 객체들을 배열로 반환 |
Object[] toArray(Object[] arr) | 지정된 배열 arr에 컬렉션의 객체들을 배열로 반환 |
중간에
Iterator iterator()
는 반복자를 취득한다고 되어있는데요. Iterator는 반복할 수 있는 객체에 접근하는 방법을 제공하는 인터페이스입니다. 반복자에 대한 내용은 추후에 따로 정리할 예정이니 지금은 이정도만 이해하시면 됩니다.
이 외에도 5~6개 정도의 메소드가 더 존재하는데, 자주 사용되는 것들만 지금은 보고 넘어가려고합니다.
위 표에 정리된 메소드들은 List, Set 컬렉션
에서 공통적으로 사용되는 것들입니다.
List 인터페이스
는 순서가 있고, 중복을 허용하는 컬렉션을 구현하기 위한 인터페이스입니다. 대표적으로는 ArraList, LinkedList, Vector, Stack
등이 있습니다.
Vecter와 Stack은 컬렉션 프레임워크가 만들어지기 전에 존재하던 컬렉션으로 구 버전 프로그램과의 호환을 위해 남겨놓은 상태입니다. ArrayList가 Vector와 Stack을 완전히 대체하므로 ArrayList를 최우선적으로 사용하는 것을 권장하고 있습니다.
List에서 사용할 수 있는 메소드는 다음과 같습니다. Collection 인터페이스로부터 상속받은 메소드들은 내용이 동일하기에 따로 적지 않았습니다.
메소드 | 설명 |
---|---|
void add(int index, Object e) | 지정된 위치 index에 객체 e 추가 |
boolean addAll(int index, Collection c) | 지정된 위치 index에 컬렉션 c 추가 |
int indexOf(Object o) | 지정된 객체 o의 위치 반환 (리스트의 처음부터 탐색) |
int lastIndexOf(Object o) | 지정된 객체 o의 위치 반환 (리스트의 마지막부터 탐색) |
ListIterator listIterator() ListIterator listIterator(int index) | 리스트 객체에 접근할 수 있는 Iterator 반환 |
Object remove(int index) | 지정된 위치의 객체를 삭제하고 삭제한 객체 반환 |
Object set(int index, Object e) | 지정된 위치게 객체 e 삽입 |
List subList(int fromIndex, int toIndex) | 지정된 범위(fromIndex~toIndex)의 객체를 리스트로 반환 |
역시 주요한 메소드들만 소개드렸습니다. 더 많은 내용은 공식 문서를 참조해주세요.
Set 인터페이스
는 순서가 없고, 중복을 허용하지 않는 컬렉션을 구현하기 위한 인터페이스입니다. 대표적으로 HashSet, TreeSet
이 있습니다.
Set의 메소드는 Collection에서 상속받은 것들과 List의 메소드와 이름, 기능이 동일하기에 위의 내용들을 참조하시면 될 것 같습니다. 전체적인 내용은 역시 공식 문서에서 확인하실 수 있습니다.
Map 인터페이스
는 키-값 쌍을 이용해서 데이터를 다루는 컬렉션 구현에 사용됩니다. 이때 키
는 중복이 불가능하지만 값
은 중복을 허용하고 있습니다. 만약 키-값 쌍이 중복된다면 기존의 키-값 쌍이 사라지고 새로 저장된 키-값 쌍만 남게 됩니다. 따라서 순서는 존재하지만 유지된다는 보장은 하지 못하는 컬렉션입니다. 대표적으로 Hashtable, HashMap, LinkedHashMap, SortedMap, TreeMap
이 있습니다.
Map 인터페이스
에서 제공하는 메소드는 다음과 같습니다.
메소드 | 설명 |
---|---|
void clear() | Map의 모든 객체 삭제 |
boolean containsKey(Object key) | 지정된 key와 일치하는 key를 가진 객체가 있는지 확인 |
boolean containsValue(Object value) | 지정된 value와 일치하는 value를 가진 객체가 있는지 확인 |
Set entrySet() | Map 내부의 키-값 쌍을 Map.Entry 타입 객체로 저장한 Set 반환 |
boolean equals(Object o) | 동일한 Map인지 판별 |
Object get(Object key) | 지정된 key가 가진 value를 반환 |
int hashCode() | Map의 해시코드 반환 |
boolean isEmpty() | Map이 비었는지 확인 |
Set keySet() | Map의 모든 key을 Set으로 반환 |
Object put(Object key, Object value) | Map의 value 객체를 key 객체와 연결(mapping)하여 저장 |
void putAll() | Map의 모든 value 객체를 key 객체와 연결하여 저장 |
Object remove(Obejct key) | 지정된 key 객체와 일치하는 키-값 쌍을 삭제 |
int size() | Map의 크기(키-값 쌍의 개수)를 반환 |
Collection values() | Map에 저장된 모든 value 객체 반환 |
key는 중복이 불가능하기 때문에 리턴타입이 Set이고, value는 중복이 가능하기 때문에 Collection 타입으로 리턴합니다.
역시 주요 메소드들만 설명드렸으니 전체 내용은 공식 문서에서 추가로 확인하실 수 있습니다.
Map.Entry
는 Map 인터페이스 내부에 정의된 내부 인터페이스입니다. 이 인터페이스의 용도는 Map의 키-값 쌍을 다루기 위해 정의되었습니다. 즉 엔트리는 키-값 쌍을 의미합니다.
Map.Entry 인터페이스
의 메소드는 다음과 같습니다.
메소드 | 설명 |
---|---|
boolean equals(Object o) | 동일한 엔트리인지 판별 |
Object getKey() | 엔트리의 key 반환 |
Object getValue() | 엔트리의 value 반환 |
int hashCode() | 엔트리의 hashcode 반환 |
Object setValue(Object value) | 엔트리의 value를 지정된 value로 변경 |
동기화는 멀티 쓰레드
프로그래밍에서 하나의 객체를 여러개의 쓰레드에서 동시에 접근하지 못하도록 막는 행위입니다.
한 쓰레드가 어떤 자원을 사용하는 동안 다른 객체가 이 자원에 접근해서 데이터를 조작하면 데이터의 일관성이 깨지므로 일관적인 상태를 유지하기 위해 한 쓰레드가 자원을 사용하는 동안 다른 쓰레드의 접근을 잠시 막습니다.
다시 돌아와서 Vector, Hashtable
과 같은 구버전 컬렉션 클래스들은 자체적으로 동기화를 지원하고 있습니다. 그렇기 때문에 멀티 쓰레드가 아닌 환경에서도 동기화를 하게 되어 효율이 떨어진다는 문제점이 발생합니다. 그래서 새로 등장한 컬렉션 프레임워크의 ArrayList, HashMap 등은 필요한 경우에만 Collections 클래스
의 동기화 메소드를 통해 동기화를 구현하도록 되어있습니다.
Collection
과Collections
는 다릅니다!둘 다
java.util
패키지에 있긴 하지만Collection
은 인터페이스이고,Collections
는 클래스입니다.
따라서 효율적인 프로그래밍을 위해 Vector는 ArrayList, Hashtable은 HashMap을 사용하는 것을 권장하고 있습니다.
이번 포스트에서는 컬렉션 프레임워크에 대한 개념들을 알아보았습니다. 다음 포스트부터 몇 개의 포스트들을 거쳐 여러가지 컬렉션 프레임워크 클래스들을 소개해보려고 합니다.