Post

[Java] 컬렉션 프레임워크 핵심 인터페이스

[Java] 컬렉션 프레임워크 핵심 인터페이스

컬렉션 프레임워크란, ‘데이터 군을 저장하는 클래스들을 표준화한 설계’를 뜻한다. 컬렉션은 다수의 데이터, 즉 데이터 그룹을 프레임워크로 표준화한 프로그래밍 방식이다.

JDK1.2 이전까지는 Vector, Hashtable, Properties와 같은 컬렉션 클래스, 다수의 데이터를 저장할 수 있는 클래스들을 서로 다른 각자의 방식으로 처리해야 했으나, JDK1.2부터 컬렉션 프레임워크가 등장하면서 다양한 종류의 컬렉션 클래스가 추가되고 모든 컬렉션 클래스를 표준화된 방식으로 다룰 수 있도록 체계화되었다.

컬렉션 프레임워크는 컬렉션, 다수의 데이터를 다루는데 필요한 다양하고 풍부한 클래스들을 제공하기 때문에 프로그래머의 부담을 덜어주고, 또한 인터페이스와 다형성을 이용한 객체지향적 설계를 통해 표준화되어 있기 때문에 사용법을 익히기에도 편리하고 재사용성이 높은 코드를 작성할 수 있다는 장점이 있다.

컬렉션 프레임워크의 핵심 인터페이스


컬렉션 프레임워크에서는 컬렉션데이터 그룹을 크게 3가지 타입이 존재한다고 인식하고 각 컬렉션을 다루는데 필요한 기능을 가진 3개의 인터페이스를 정의하였다. 그리고 인터페이스 List와 Set의 공통된 부분을 다시 뽑아서 새로운 인터페이스인 Collection을 추가로 정의하였다.

컬렉션 프레임워크의 핵심 인터페이스간의 상속계층도

컬렉션 프레임워크의 핵심 인터페이스간의 상속계층도

인터페이스 List와 Set을 구현한 컬렉션 클래스들은 서로 많은 공통부분이 있어서, 공통된 부분을 다시 뽑아 Collection인터페이스를 정의할 수 있었지만 Map인터페이스는 이들과는 전혀 다른 형태로 컬렉션을 다루기 때문에 같은 상속계층도에 포함되지 못했다. 이러한 설계는 객체지향언어의 장점을 극명히 보여준다.

💡 참고
JDK1.5부터 Iterable인터페이스가 추가되고 이를 Collection인터페이스가 상속받도록 변경되었으나 이것은 ㅁ단지 인터페이스들의 공통적인 메서드인 iterator()를 뽑아서 중복을 제거하기 위한 것에 불과하므로 상속계층도에서 별 의미가 없다.

인터페이스특징
List 순서가 있는 데이터의 집합. 데이터의 중복을 허용한다.
예) 대기자 명단
구현클래스 : ArrayList, LinkedList, Stack, Vector 등
Set 순서를 유지하지 않는 데이터의 집합, 데이터의 중복을 허용하지 않는다.
예) 양의 정수집합, 소수의 집합
구현클래스 : HashSet, TreeSet 등
Map 키(key)와 값(value)의 쌍으로 이루어진 데이터의 집합
순서는 유지되 않으며, 키는 중복을 허용하지 않고, 값은 중복을 허용한다.
예) 양의 정수집합, 소수의 집합
구현클래스 : HashMap, TreeMap, Hashtable, Properties 등

컬렉션 프레임워크의 모든 클래스들은 List, Set, Map 중의 하나를 구현하고 있으며, 구현한 인터페이스의 이름이 클래스의 이름에 포함되어있어 이름만으로도 클래스의 특징을 쉽게 알 수 있도록 되어있다. 그러나 Vector, Stack, Hashtable, Properties와 같은 클래스들은 컬렉션 프레임워크가 만들어지기 이전부터 존재하던 것이기 때문에 컬렉션 프레임워크의 명명법을 따르지 않는다.

Vector나 Hashtable과 같은 기존의 컬렉션 클래스들을 호환하기 위해, 설계를 변경해서 남겨두었지만 가능하면 사용하지 않는 것이 좋다. 대신 새로 추가된 ArrayList와 HashMap을 사용하자.,

Vector클래스의 상속계층도 변화 - 왼쪽이 JDK1.2이전, 오른쪽이 이후

Vector클래스의 상속계층도 변화 - 왼쪽이 JDK1.2이전, 오른쪽이 이후

Collection 인터페이스

메서드설명
boolean add(Object o)
boolean addAll(Collection c)
지정된 객체(o) 또는 Collection(c)의 객체들을 Collection에 추가한다.
void clear()Collection의 모든 객체를 삭제한다.
boolean contains(Object o)
boolean containsAll(Collection c)
지정된 객체(o) 또는 Collection의 객체들이 Collection에 포함되어 있는지 확인한다.
boolean equals(Object o)동일한 Collection인지 비교한다.
int hashCode()Collection의 hash code를 반환한다.
boolean isEmpty()Collection이 비어있는지 확인한다.
Iterator iterator()Collection의 Iterator를 얻어서 반환한다.
boolean remove(Object o)지정된 객체를 삭제한다.
boolean removeAll(Collection c)지정된 Collection에 포함된 객체들을 삭제한다.
boolean retainAll(Collection c) 지정된 Collection에 포함된 객체만을 남기고 다른 객체들은 Collection에서 삭제한다. 이 작업으로 인해 Collection에 변화가 있으면 true를 그렇지 않으면 false를 반환한다.
int size()Collection에 저장된 객체의 개수를 반환한다.
Object[] toArray()Collection에 저장된 객체를 객체배열(Object[])로 반환한다.
Object[] toArray(Object[] a)지정된 배열에 Collection의 객체를 저장해서 반환한다.

💡 참고
JDK1.8부터 추가된 parallelStream, removelf, stream, forEach 등은 향후 람다 스트림 포스팅에서 설명하겠다.

Collection인터페이스는 컬렉션 클래스에 저장된 데이터를 읽고, 추가하고 삭제하는 등 컬렉션을 다루는데 가장 기본적인 메서드들을 정의하고 있다.

그리고 Java API문서를 보면 위 표에서 사용된 ‘Object’가 아닌 ‘E’로 표기되어있는데, E는 특정 타입을 의미하는 것으로 JDK1.5부터 추가된 제네릭에 의한 표기이다.

List 인터페이스

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

List의 상속계층도

List의 상속계층도

List인터페이스에 정의된 메서드는 다음과 같다. Collection인터페이스로부터 상속받은 것들은 제외하였다.

메서드설명
void add(int index, Object element)
boolean addAll(int index, Collection c)
지정된 위치(index)에 객체(element) 또는 컬렉션에 포함된 객체들을 추가한다.
Object get(int index)지정된 위치(index)에 있는 객체를 반환한다.
int indexOf(Object o) 지정된 객체의 위치(index)를 반환한다.
(List의 첫 번쨰 요소부터 역방향으로 찾는다.)
int lastIndexOf(Object o) 지정된 객체의 위치(index)를 반환한다.
(List의 마지막 요소부터 역방향으로 찾는다.)
ListIterator listIterator()
ListIterator listIterator(int index)
List의 객체에 접근할 수 있는 ListIterator를 반환한다.
Object remove(int index)지정된 위치(index)에 있는 객체를 삭제하고 삭제된 객체를 반환한다.
Object set(int index, Object element)지정된 위치(index)에 객체(element)를 저장한다.
void sort(Comparator c)지정된 비교자(comparator)로 List를 정렬한다.
List subList(int fromIndex, int toIndex)지정된 범위(fromIndex부터 toIndex)에 있는 객체를 반환한다.

Set인터페이스

Set인터페이스는 중복을 허용하지 않고 저장순서가 유지되지 않는 컬렉션 클래스를 구현하는데 사용된다. Set인터페이스를 구현한 클래스로는 HashSet, TreeSet 등이 있다.

Set의 상속계층도

Set의 상속계층도

Map인터페이스

Map인터페이스는 키(key)와 값(value)을 하나의 쌍으로 묶어서 저장하는 컬렉션 클래스를 구현하는데 사용된다. 키는 중복될 수 없지만 값은 중복을 허용한다. 기존에 저장된 데이터와 중복된 키와 값을 저장하면 기존의 값은 없어지고 마지막에 저장된 값이 남게된다. Map인터페이스를 구현한 클래스로는 Hashable, HashMap, LinkedHashMap, SortedMap, TreeMap 등이 있다.

Map의 상속계층도

Map의 상속계층도
메서드설명
void clear()Map의 모든 객체를 삭제한다.
boolean containsKey(Object key)지정된 key객체와 일치하는 Map의 key객체가 있는지 확인한다.
boolean containsValue(Object value)지정된 value객체와 일치하는 Map의 value객체가 있는지 확인한다.
Set entrySet()Map에 저장되어 있는 key-value쌍을 Map.Entry타입의 객체로 저장한 Set으로 반환한다.
boolean equals(Object o)동일한 Map인지 비교한다.
Object get(Object key)지정한 key객체에 대응하는 value객체를 찾아서 반환한다.
int hashCode()해시코드를 반환한다.
boolean isEmpty()Map이 비어있는지 확인한다.
Set keySet()Map에 저장된 모든 key객체를 반환한다.
Object put(Object key, Object value)Map에 value객체를 key객체에 연결(mapping)하여 저장한다.
void putAll(Map t)지정된 Map의 모든 key-value쌍을 추가한다.
Object remove(Object key)지정한 key객체와 일치하는 key-value객체를 삭제한다.
int size()Map에 저장된 key-value쌍의 개수를 반환한다.
Collection values()Map에 저장된 모든 value객체를 반환한다.

values()에서는 반환타입이 Collection이고, keySet()에서는 반환타입이 Set인 것에 주목하자. Map인터페이스에서 값(value)은 중복을 허용하기 때문에 Collection타입으로 반환하고, 키(key)는 중복을 허용하지 않기 때문에 Set타입으로 반환한다.

Map.Entry인터페이스

Map.Entry인터페이스는 Map인터페이스의 내부 인터페이스이다. 내부 클래스와 같이 인터페이스도 인터페이스 안에 인터페이스를 정의하는 내부 인터페이스를 정의하는 것이 가능하다.

Map에 저장되는 key-value쌍을 다루기 위해 내부적으로 Entry인터페이스를 정의해 놓았다. 이것은 보다 객체지향적으로 설계하도록 유도하기 위한 것으로 Map인터페이스를 구현하는 클래스에서는 Map.Entry인터페이스도 함께 구현해야한다.

다음은 Map인터페이스의 소스코드의 일부이다.

1
2
3
4
5
6
7
8
9
10
11
public interface Map {
    ...
    public static interface Entry {
        Object getKey();
        Object getValue();
        Object setValue(Object value);
        boolean equals(Object o);
        int hashCode();
        ...     // JDK8.0부터 추가된 메서드는 생략
    }
}
메서드설명
boolean equals(Object o)동일한 Entry인지 비교한다.
Object getKey()Entry의 key객체를 반환한다.
Object getValue()Entry의 value객체를 반환한다.
int hashCode()Entry의 해시코드를 반환한다.
Object setValue(Object value)Entry의 value객체를 지정된 객체로 바꾼다.

읽어주셔서 감사합니다. 😊

Reference
자바의 정석 - 남궁성

This post is licensed under CC BY 4.0 by the author.