Collection 프레임워크

개발자가 되고 싶어요 ㅣ 2024. 3. 1. 16:45

컬렉션 프레임워크

 

자바는 널리 알려져 있는 자료구조를 바탕으로 객체들을 효율적으로 추가, 삭제, 검색할 수 있도록 관련된 인터페이스와 클래스들을 java.util 패키지에 포함시켜 놓았다. 이들을 총칭해서 컬렉션 프레임워크라고 부른다.

컬렉션 프레임워크는 몇 가지 인터페이스를 통해서 다양한 컬렉션 클래스를 이용할 수 있도록 설계되어 있다. 주요 인터페이스로는 List, Set, Map이 있는데, 이 인터페이스로 사용 가능한 컬렉션 객체의 종류는 다음과 같다.

 

List와 Set은 객체를 추가, 삭제, 검색하는 방법에 있어서 공통점이 있기 때문에 공통된 메소드만 따로 모아 Collection 인터페이스로 정의해 두고 이것을 상속하고 있다. Map은 키와 값을 하나의 쌍으로 묶어서 관리하는 구조로 되어 있어 List 및 Set과는 사용 방법이 다르다. 다음은 각 인터페이스별로 사용할 수 있는 컬렉션의 특징을 정리한 것이다.

인터페이스 분류 특징 구현 클래스
Colleciton List - 순서를 유지하고 저장, - 중복 저장 가능 ArrayList, Vector, LinkedList
Set - 순서를 유지하지 않고 저장, - 중복 저장 안됨 HashSet, TreeSet
Map - 키와 값으로 구성된 엔트리 저장, - 키는 중복 저장 안됨 HashMap, Hashtable, TreeMap, Properties

 

List 컬렉션

List 컬렉션은 객체를 인덱스로 관리하기 때문에 객체를 저장하면 인덱스가 부여되고 인덱스로 객체를 검색, 삭제할 수 있는 기능을 제공한다.

List 컬렉션에는 ArrayList, Vector, LinkedList 등이 있는데, List 컬렉션에서 공통적으로 사용 가능한 List 인터페이스 메소드는 다음과 같다. 인덱스로 객체들이 관리되기 때문에 인덱스를 매개값으로 갖는 메소드들이 많다.

기능 메소드 설명
객체 추가 boolean add(E e) 주어진 객체를 맨 끝에 추가
void add(int index, E element) 주어진 인덱스에 객체를 추가
set(int index, E element) 주어진 인덱스의 객체를 새로운 객체로 바꿈
객체 검색 boolean contains(Object o) 주어진 객체가 저장되어 있는지 여부
E get(int index) 주어진 인덱스에 저장된 객체를 리턴
isEmpty() 컬렉션이 비어 있는지 조사
int size() 저장되어 있는 전체 객체 수를 리턴
객체 삭제 void clear() 저장된 모든 객체를 삭제
E remove(int index) 주어진 인덱스에 저장된 객체를 삭제
boolean remove(Object o) 주어진 객체를 삭제

 

ArrayList

ArrayList는 List컬렉션에서 가장 많이 사용하는 컬렉션이다. ArrayList에 객체를 추가하면 내부 배열에 객체가 저장된다. 일반 배열과의 차이점은 ArrayList는 제한 없이 객체를 추가할 수 있다는 것이다.

List 컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 저장한다. 또한 동일한 객체를 중복 저장할 수 있는데, 이 경우에는 동일한 번지가 저장된다. null 또한 저장이 가능하다.

ArrayList는 저장과 삭제 시 전체 인덱스가 1씩 밀리거나 1씩 땡겨지기 때문에 빈번한 객체 삭제와 삽입이 일어나는 곳에서 사용하는 것은 바람직하지 않다. 이런 경우는 LinkedList가 적절하다.

주요 함수: https://tmddus3002.tistory.com/58

 

Array, List

자료구조 Array (배열) 정의: Array는 동일한 자료형의 요소들을 하나의 변수로 저장하는 자료구조이다. 각 요소는 고유의 인덱스를 가지며, 메모리에 연속적으로 할당된다. 탄생 이유: 고정된 크기

tmddus3002.tistory.com

 

 

Vector

vector는 ArrayList와 동일한 내부 구조를 가지고 있다. 차이점은 Vector는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 Vector() 메소드를 실행할 수 없다는 것이다. 그렇기 때문에 멀티 스레드 환경에서는 안전하게 객체를 추가 또는 삭제할 수 있다.

 

LinkedList

LinkedList는 ArrayList와 사용 방법은 동일하지만 내부 구조는 완전히 다르다. ArrayList는 내부 배열에 객체를 저장하지만, LinkedList는 인접 객체를 체인처럼 연결해서 관리한다.

LinkedList는 특정 위치에서 객체를 삽입하거나 삭제하면 바로 앞뒤 링크만 변경하면 되므로 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList보다 좋은 성능을 발휘한다.

 

Set 컬렉션

List 컬렉션은 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지되지 않는다. 또한 객체를 중복해서 저장할 수 없고, 하나의 null만 저장할 수 있다. Set 컬렉션은 수학의 집합에 비유될 수 있다.

집합은 순서와 상관없고 중복이 허용되지 않기 때문이다. 따라서 저장할 때와 조회할 때의 순서가 다를 수 있다.

Set 컬렉션에는 HashSet, LinkedHashSet, TreeSet 등이 있는데, Set 컬렉션에서 공통적으로 사용 가능한 Set 인터페이스의 메소드는 다음과 같다. 인덱스로 관리하지 않기 때문에 인덱스를 매개값으로 갖는 메소드가 없다.

기능 메소드 설명
객체 추가 boolean add(E e) 주어진 객체를 성공적으로 저장하면 true를 리턴하고 중복 객체면 false를 리턴
객체 검색 boolean contains(Object o) 주어진 객체가 저장되어 있는지 여부
isEmpty() 컬렉션이 비어 있는지 조사
Iterator<E> iterator() 저장된 객체를 한 번씩 가져오는 반복자 리턴
int size() 저장되어 있는 전체 객체 수 리턴
객체 삭제 void clear() 저장된 모든 객체를 삭제
boolean remove(Object o) 주어진 객체를 삭제

 

HashSet

Set 컬렉션 중에서 가장 많이 사용되는 것이 HashSet이다. HashSet은 동일한 객체는 중복 저장하지 않는다. 여기서 동일한 객체란 동등 객체를 말한다. HashSet은 다른 객체라도 hashCode() 메소드의 리턴값이 같고, equals() 메소드가 true를 리턴하면 동일한 객체라고 판단하고 중복 저장하지 않는다.

Set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드가 없다. 대신 객체를 한 개씩 반복해서 가져와야 하는데, 여기에는 두 가지 방법이 있다. 하나는 for문을 이용하는 것이고, 다른 하나는 iterator()메소드로 반복자를 얻어 객체를 하나씩 가져오는 것이다.

Iterator<E> iterator = set.iterator();

iterator는 Set컬렉션의 객체를 가져오거나 제거하기 위해 다음 메소드를 제공한다.

리턴 타입 메소드명 설명
boolean hasNext() 가져올 객체가 있으면 true를 리턴하고 없으면 false를 리턴한다.
E next() 컬렉션에서 하나의 객체를 가져온다.
void remove() next()로 가져온 객체를 Set 컬렉션에서 제거한다.

 

Map 컬렉션

Map 컬렉션으로 구성된 엔트리 객체를 저장한다. 여기서 키와 값은 모두 객체이다. 키는 중복 저장할 수 없지만 값은 중복 저장 할 수 있다. 기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대체된다.

Map 컬렉션에는 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다. Map 컬렉션에서 공통적으로 사용 가능한 Map 인터페이스 메소드는 다음과 같다. 키로 객체들을 관리하기 때문에 키를 매개값으로 갖는 메소드가 많다.

기능 메소드 설명
객체 추가 V Put(K key, V value) 주어진 키와 값을 추가, 저장이 되면 값을 리턴
객체 검색 boolean containsKey(Object key) 주어진 키가 있는지 여부
boolean containsValue(Object value) 주어진 값이 있는지 여부
Set<Map.Entry<K,V>> entrySet() 키와 값의 쌍으로 구성된 모든 Map.Entry 객체를 Set에 담아서 리턴
V get(Object key) 주어진 키의 값을 리턴
booelan isEmpty() 컬렉션이 비어있는지 여부
Set<K> keySet() 모든 키를 Set 객체에 담아서 리턴
int size() 저장된 키의 총 수를 리턴
Collection<V> values() 저장된 모든 값 Collection에 담아서 리턴
객체 삭제 void clear() 모든 Map.Entry(키와 값)를 삭제
V remove(Object key) 주어진 키와 일치하는 Map.Entry 삭제, 삭제가 되면 값을 리턴

 

HashMap

HashMap은 키로 사용할 객체가 hasecode() 메소드의 리턴값이 같고 equals() 메소드가 true를 리턴할 경우, 동일 키로 보고 중복 저장을 허용하지 않는다.

 

Hashtable

Hashtable은 HashMap과 동일한 내부 구조를 가지고 있다. 차이점은 Hashtable은 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 Hashtable의 메소드들을 실행할 수 없다는 것이다. 따라서 멀티 스레드 환경에서도 안전하게 객체를 추가,삭제할 수 있다.

 

Properties

PropertiesHashtable의 자식 클래스이기 때문에 Hashtable의 특징을 그대로 가지고 있다. Properties는 키와 값을 String 타입으로 제한한 컬렉션이다. Properties는 주로 확장자가 .properties인 프로퍼티 파일을 읽을 때 사용한다.

프로퍼티 파일은 다음과 같이 키와 값이 = 기호로 연결되어 있는 텍스트 파일이다. 일반 텍스트 파일과는 다르게 ISO 8859-1 문자셋으로 저장되며, 한글일 경우에는 \u+유니코드로 표현되어 저장된다.

 

검색 기능을 강화시킨 컬렉션

컬렉션 프레임워크는 검색 기능을 강화시킨 TreeSetTreeMap을 제공한다. 이름에서 알 수 있듯이 TreeSetSet 컬렉션이고, TreeMapMap 컬렉션이다.

TreeSet

Treeset이진 트리를 기반으로 한 Set 컬렉션이다. 이진 트리여러 개의 노드가 트리 형태로 연결된 구조로, 루트 노드라고 불리는 하나의 노드에서 시작각 노드에 최대 2개의 노드를 연결할 수 있는 구조를 가지고 있다.

 

TreeSet에 객체를 저장하면 부모 노드의 객체와 비교해서 낮은 것은 왼쪽 자식 노드에, 높은것은 오른쪽 자식 노드에 자동으로 정렬된다.

 

TreeSet을 생성할 때는 Set<Object o> treeSet= new TreeSet<>()으로 해도 되지만 TreesSet<Object o> treeSet = new TreeSet<>()으로 생성하는 것을 권장한다.

 

Set 타입 변수에 대입해도 되지만 TreeSet 타입으로 대입한 이유는 검색 관련 메소드가 TreeSet에만 정의되어 있기 때문이다. 다음은 TreeSet이 가지고 있는 검색 관련 메소드들이다.

리턴 타입 메소드 설명
E first() 제일 낮은 객체를 리턴
E last() 제일 높은 객체를 리턴
E lower(E e) 주어진 객체보다 바로 아래 객체를 리턴
E higher(E e) 주어진 객체보다 바로 위 객체를 리턴
E floor(E e) 주어진 객체와 동등한 객체가 있으면 리턴, 만약 없다면 주어진 객체의 바로 아래의 객체를 리턴
E ceiling(E e) 주어진 객체와 동등한 객체가 있으면 리턴, 만약 없다면 주어진 객체의 바로 위의 객체를 리턴
E pollFirst() 제일 낮은 객체를 꺼내오고 컬렉션에서 제거함
E pollLast() 제일 높은 객체를 꺼내오고 컬렉션에서 제거함
Iterator<E> descendingIterator() 내림차순으로 정렬된 Iterator를 리턴
NavigableSet<E> descendingSet() 내림차순으로 정렬된 NavigableSet을 리턴
NavigableSet<E> headSet(E toElemnet,
              boolean inclusive)
주어진 객체보다 낮은 객체들을 NavigableSet으로 리턴. 주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐
NavigableSet<E> tailSet(E toElemnet,
           boolean inclusive)
주어진 객체보다 높은 객체들을 NavigableSet으로 리턴. 주어진 객체 포함 여부는 두 번째 매개값에 따라 달라짐
NavigableSet<E> subSet(E fromElement,
            boolean fromInclusive,              E toElement,
            boolean toInclusive)
시작과 끝으로 주어진 객체 사이의 객체들을 NavigableSet으로 리턴. 시작과 끝 객체의 포함 여부는 두 번째, 네 번째 매개값에 따라 달라짐

 

TreeMap

TreeMap은 이진 트리를 기반으로 한 Map 컬렉션이다. TreeSet과의 차이점은 키와 값이 저장된 Entry를 저장한다는 점이다.

TreeMap에 엔트리를 저장하면 키를 기준으로 자동 정렬되는데, 부모 키 값과 비교해서 낮은 것은 왼쪽, 높은 것은 오른쪽 자식 노드에 Entry 객체를 저장한다.

 

TreeMap을 생성할 때는 Map<K,V> treeMap = new TreeMap<>()으로 해도 되지만 TreesMap<K, V> treeMap= new TreeSet<>()으로 생성하는 것을 권장한다.

리턴 타입 메소드 설명
Map.Entry<K,V> firstEntry() 제일 낮은 Map.Entry를 리턴
Map.Entry<K,V> lastEntry() 제일 높은 Map.Entry를 리턴
Map.Entry<K,V> lowerEntry(K key) 주어진 키보다 바로 아래 Map.Entry를 리턴
Map.Entry<K,V> higherEntry(K key) 주어진 키보다 바로 위 Map.Entry를 리턴
Map.Entry<K,V> floorEntry(K key) 주어진 키와 동등한 키가 있으면 해당 Map.Entry를 리턴, 없다면 주어진 키 바로 아래의 Map.Entry를 리턴
Map.Entry<K,V> ceilingEntry(K key) 주어진 키와 동등한 키가 있으면 해당 Map.Entry를 리턴, 없다면 주어진 키 바로 위의 Map.Entry를 리턴
Map.Entry<K,V> pollFirstEntry() 제일 낮은 Map.Entry를 꺼내오고 컬렉션에서 제거함
Map.Entry<K,V> pollLastEntry() 제일 높은 Map.Entry를 꺼내오고 컬렉션에서 제거함
NavigableSet<K> descendingKeySet() 내림차순으로 정렬된 키의 NavigableSet을 리턴
NavigableSet<K,V> descendingMap() 내림차순으로 정렬된 Map.Entry의 NavigableMap을 리턴
NavigableSet<K,V> headMap(K toKey,boolean inclusive) 주어진 키보다 낮은 Map.Entry들을 NavigableMap으로 리턴. 주어진 키의 Map.Entry 포함 여부는 두 번째 매개값에 따라 달라짐
NavigableSet<K,V> tailMap(K fromKey,boolean inclusive) 주어진 키보다 높은 Map.Entry들을 NavigableMap으로 리턴. 주어진 키의 Map.Entry 포함 여부는 두 번째 매개값에 따라 달라짐
NavigableSet<K,V> subMap(K fromKey,boolean inclusive, K toKey, boolean toInclusive) 시작과 끝으로 주어진 키 사이의 Map.Entry들을 NavigableMap 컬렉션으로 반환. 시작과 끝 키의 Map.Entry 포함 여부는 두 번째, 네 번째 매개값에 따라 달라짐

 

Comparable과 Comparator

TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체는 저장과 동시에 오름차순으로 정렬되는데, 어떤 객체든 정렬될 수 있는 것은 아니고 객체가 Comparable 인터페이스를 구현하고 있어야 가능하다. Integer, Double, String 타입은 모두 Comparable을 구현하고 있기 때문에 상관 없지만, 사용자 정의 객체를 저장할 때에는 반드시 Comparable을 구현하고 있어야 한다.

Comparable 인터페이스에는 compareTo() 메소드가 정의되어 있다. 따라서 사용자 정의 클래스에서 이 메소드를 재정의해서 비교 결과를 정수 값으로 리턴해야 한다.

리턴 타입 메소드 설명
int compareTo(T o) 주어진 객체와 같으면 0을 리턴. 주어진 객체보다 적으면 음수를 리턴. 주어진 객체보다 크면 양수를 리턴
int compare(T o1, T o2) o1과 o2가 동등하다면 0을 리턴. o1이 o2보다 앞에 오게 하려면 음수를 리턴. o1이 o2보다 뒤에 오게 하려면 양수를 리턴

 

LIFO와 FIFO 컬렉션

후입선출(LIFO)은 나중에 넣은 객체가 먼저 빠져나가고, 선입선출(FIFO)은 먼저 넣은 객체가 먼저 빠져나가는 구조를 말한다. 컬렉션 프레임워크는 LIFO 자료구조를 제공하는 스택 클래스FIFO 자료구조를 제공하는 큐 인터페이스를 제공하고 있다.

스택을 응용한 대표적인 예가 JVM 스택 메모리이다. 스택 메모리에 저장된 변수는 나중에 저장된 것부터 제거된다. 를 응용한 대표적인 예가 스레드풀의 작업 큐이다. 작업 큐는 먼저 들어온 작업부터 처리한다.

 

Stack

Stack 클래스는 LIFO 자료구조를 구현한 클래스이다.

리턴 타입 메소드 설명
E push(E item) 주어진 객체를 스택에 넣는다.
E pop() 스택의 맨 위 객체를 빼낸다.
boolean isEmpty() 스택이 비어 있다면 true를 반환하고, 비어있지 않다면 false를 반환한다.

 

Queue

Queue 인터페이스는 FIFO 자료구조에서 사용되는 메소드를 정의하고 있다.

리턴 타입 메소드 설명
boolean offer(E e) 주어진 객체를 큐에 넣는다.
E poll() 큐에서 객체를 빼낸다.

Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList이다. 그렇기 때문에 LinkedList 객체를 Queue 인터페이스 변수에 대입할 수 있다.

'자료구조&알고리즘' 카테고리의 다른 글

tmp  (0) 2024.05.19
tmp  (0) 2024.04.20
Array, List  (0) 2024.02.03