11. 컬렉션 프레임웍

KOO HEESEUNG·2021년 10월 4일
0

Java의 정석

목록 보기
5/8
post-thumbnail

1. 컬렉션 프레임웍이란

1-1. 정의

컬렉션 : 여러 객체를 모아놓은 것
프레임워크 : Frame(틀) + work(작업). 표준화, 정형화.
컬렉션(다수의 객체)을 다루기 위한 표준화된 프로그래밍 방식.

1-2. 핵심 인터페이스

List와 Set은 Collection 인터페이스의 자손. Map은 둘과는 다른 형태이기 때문에 상속 계층도에 포함되지 않는다.

인터페이스특징
List저장 순서 O, 중복 허용 O.
Set저장 순서 X, 중복 허용 X.
Mapkey=value로 이루어진 데이터 집합. 순서 X, key는 중복 허용 X, value는 중복 허용 O.

1-3. Collection 인터페이스

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

반환타입이 boolean인 것들은 작업을 성공하거나 사실이면 true를 반환.


2. List 인터페이스

저장 순서가 유지되고, 중복을 허용하는 컬렉션 구현에 사용한다.

Vector와 ArrayList는 거의 비슷하다. Vector는 구버전, ArrayList는 신버전. 웬만하면 ArrayList를 사용하는 것을 권장.

2-1. 메서드

메서드설명
void add(int index, Object element)
boolean addAll(int index, Collection c)
지정된 위치(index)에 객체(element)나 컬렉션에 포함된 객체(c) 추가
Object get(int index)지정된 위치(index)에 있는 객체 반환(읽기)
Object set(int index, Object element)지정된 위치(index)에 객체 저장(변경)
int indexOf(Object o)
int lastIndexOf(Object o)
지정된 객체의 위치(index) 반환
indexOf()는 순방향, lastIndexOf()는 역방향으로 검색
Object remove(int index)지정된 위치(index)에 있는 객체 삭제하고, 이를 반환
void sort(Comparator c)지정된 비교자(c)로 List 정렬
List subList(int fromIndex, int toIndex)지정된 범위에 있는 객체 반환

2-2. ArrayList

배열기반. 데이터 저장공간으로 Object 배열을 사용한다. 모든 종류의 객체 저장 가능.

ArrayList의 요소를 삭제하고 싶다면 마지막부터 하는 것이 성능상 이득이다. 앞에서부터 할 경우, 데이터의 위치가 바뀌기 때문에 번거롭고, 더 긴 시간이 소요됨.

앞에서부터 삭제하는 방법 : 삭제할 데이터 다음의 데이터들을 한칸씩 위로 복사 -> 마지막 데이터를 null로 변경 -> 데이터 개수 1 감소시키기.

메서드

메서드설명
ArrayList()
ArrayList(Collection c)
ArrayList(int initialCapacity)
생성자. 크기가 0,
컬렉션 c가 저장된,
지정된 용량(initialCapacity)을 갖는 ArrayList 생성.
Object clone()ArrayList 복제
void ensureCapacity(int minCapacity)ArrayList 용량이 최소한 minCapacity가 되도록
void trimToSize()용량을 크기에 맞게 줄임(빈 공간 없앤다.)

2-3. LinkedList

배열의 단점을 보완하기 위해 불연속적으로 존재하는 데이터를 서로 연결한 것.

배열의 장단점

  • 장점 : 구조가 단순. 데이터 읽어오는 데 걸리는 시간이 짧다.
  • 단점 : 크기 변경 불가. 비순차적 데이터 변경(추가/삭제) 시간이 길다.

위 그림에서 보이는 하나하나를 노드(Node)라고 하며, 노드는 저장된 데이터와 다음 노드 주소를 가진다.

이렇게 하면 배열의 단점인 비순차적 데이터 변경이 간편하다.

LinkedList 에서 데이터 변경

  • 삭제 : 삭제하고 싶은 노드의 이전 노드에서 다음 노드 주소를 변경.(참조변경 1회)
  • 추가 : 1. 노드 생성 2. 추가할 노드와 그 위치 이전 노드의 다음 노드 주소를 변경 (참조변경 2회)

그러나 LinkedList는 데이터 접근성이 나쁘다는 단점이 존재한다. 이를 보완한 것이 이중 연결 리스트(DoublyLinkedList). 하나의 노드가 직전 노드와 다음 노드의 주소를 갖는다.

2-4. Stack과 Queue

스택 : LIFO(후입선출) 구조. 배열기반 컬렉션 클래스에 적합. 활용 예) 웹브라우저 뒤로/앞으로

큐 : FIFO(선입선출) 구조. 연결기반 컬렉션 클래스에 적합. 활용 예) 최근 사용 문서, 인쇄작업 대기목록

Stack 메서드

메서드설명
boolean empty()스택이 비어 있는지 알려줌
Object peek()스택 맨 위에 저장된 객체 반환. 객체 꺼내는 것 아님. 스택이 비어 있으면 EmptyStackException 발생
Object pop()스택 맨 위에 저장된 객체 반환. 객체를 꺼냄. 스택이 비어 있으면 EmptyStackException 발생
Object push(Object item)스택에 객체(item) 저장
int search(Object o)스택에서 객체 o 찾아서 위치 반환(위치는 0이 아닌 1부터 시작). 없으면 -1 반환

Queue 메서드

메서드설명
boolean add(Object o)객체 o를 큐에 추가. 성공시 true 반환. 저장공간 부족하면 IllegalStateException 발생
Object remove()큐에서 객체 꺼내 반환. 비어있으면 NoSuchElementException 발생
Object element()삭제 없이 요소 읽기. 비어있으면 NoSuchElementException 발생
boolean offer(Object o)큐에 객체 저장. 성공시 true 반환. 예외 발생하지 않음.
Object poll()큐에서 객체 꺼내서 반환. 비어있으면 null 반환. 예외 발생하지 않음.
Object peek()삭제없이 요소 읽기. 비어있으면 null 반환.

3. Set 인터페이스

저장순서가 유지되지 않고, 중복도 허용하지 않는 컬렉션 구현에 사용한다.

보통 HashSet 을 많이 사용하고, 순서를 유지하려면 LinkedHashSet 클래스를 사용한다.

3-1. 메서드

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

3-2. HashSet

Set 인터페이스를 구현한 대표적 컬렉션 클래스.

정렬은 순서가 유지되어야 하기 때문에 Set은 정렬이 불가하므로, Set을 정렬하기 위해서는 List로 옮긴 후 그 List를 정렬하는 방식을 택한다.

HashSet은 객체를 저장하기 전에 기존에 같은 객체가 있는지 확인 후 없으면 저장하므로, 반드시 equals()와 hashCode()가 오버라이딩 되어 있어야 한다.

메서드

메서드설명
HashSet()
HashSet(Collection c)
HashSet(int initialCapacity)
HashSet(int initialCapacity, float loadFactor)
생성자.
컬렉션 c를 포함하는 HashSet 객체 생성
initialCapacity를 초기용량으로 함.
loadFactor를 지정하여 지정한 만큼 차면 용량을 2배 늘림.
boolean add(Object o)새로운 객체 저장
Object clone()HashSet 복제해서 반환

3-3. TreeSet

이진 탐색 트리로 구현된 컬렉션 클래스. 범위 탐색과 정렬에 유리하다. HashSet 보다는 데이터 추가/삭제에 시간이 더 걸린다.

이진 트리

여러 개의 노드가 서로 연결된 구조.

하나의 노드에 연결된 노드가 최대 2개(0~2).
위아래로 연결된 노드는 부모-자식관계에 있음.

이진 탐색 트리

부모 노드 왼쪽에는 부모 노드 값보다 작은 값의 자식 노드, 오른쪽은 큰 값의 자식 노드를 저장.

데이터가 많아질수록 추가/삭제에 시간이 더 걸리는 단점이 존재한다. 비교횟수가 증가하기 때문.

메서드

메서드설명
TreeSet()
TreeSet(Collection c)
TreeSet(Comparator comp)
생성자.
컬렉션 c를 저장하는 TreeSet 생성
정렬기준 comp로 정렬하는 TreeSet 생성.
Object first()
Object last()
오름차순일 때 제일 작은 객체 반환
제일 큰 객체 반환
Object ceiling(Object o)
Object floor(Object o)
객체 o와 같거나 가장 가까운 큰 것 반환.
같거나 가장 가까운 작은 것 반환. 없으면 null.
Object higher(Object o)
Object lower(Object o)
객체 o보다 큰 값 중 가장 가까운 값의 객체 반환.
작은 값 중 가장 가까운.
SortedSet subSet(Object from, Object to)범위 검색(from ~ to)의 결과 반환.(to는 범위 포함 X)
SortedSet headSet(Object to)
SortedSet tailSet(Object from)
to보다 작은 값 반환.
큰 값 반환.

4. Map 인터페이스

key와 value 의 한 쌍으로 저장. key는 중복을 허용하지 않으나, value는 중복을 허용함.

핵심 클래스는 HashMap과 TreeMap.

4-1. 메서드

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

4-2. HashMap과 Hashtable

Map 인터페이스를 구현한 컬렉션 클래스. 데이터를 key와 value 한 쌍으로 저장. 해싱 기법으로 데이터를 저장하며, 데이터가 많아도 검색이 빠르다.

해싱(hashing)

해시함수를 이용하여 해시테이블에 데이터 저장 및 읽어오는 방식.

  1. key로 해시함수를 호출하여 해시코드를 얻는다.
  2. 해시코드에 대응하는 링크드리스트를 배열에서 찾는다.
  3. 링크드리스트에서 key와 일치하는 데이터를 찾는다.

※ 해시함수는 같은 key에 대해 항상 같은 해시코드를 반환해야 한다. 서로 다른 key여도 같은 값의 해시코드를 반환할 수 있다.

※ 해시테이블은 배열과 링크드 리스트가 조합된 형태. 배열의 장점인 접근성과, 링크드리스트의 장점인 변경이 유리하다는 점을 합친 것.

Hashtable과 HashMap은 거의 동일하지만, 동기화 여부에서 차이가 존재한다.(Hashtable은 동기화가 되어 있음)

순서를 유지하려면 LinkedHashMap 클래스를 사용한다.

메서드

메서드설명
HashMap()
HashMap(int initialCapacity)
HashMap(int initialCapacity, float loadFactor)
HashMap(Map m)
생성자.
Object replace(Object key, Object value)
boolean replace(Object key, Object oldValue, Object newValue)
key 값을 value로 대체
key와 oldValue가 모두 일치하는 경우에만 newValue로 대체
Object getOrDefault(Object key, Object defaultValue)key값을 반환. 못찾으면 defaultValue로 지정된 객체를 반환.

5. Iterator

컬렉션에 저장된 데이터를 읽어오기 위한 인터페이스. 컬렉션들마다 구조가 다 달라서 조회하는 방법이 다르므로, 이를 표준화하기 위함.

구버전은 Enumeration. ListIterator는 Iterator의 양방향 조회가 가능하도록 기능을 향상시킨 인터페이스.

핵심 메서드는 boolean hasNext()Object next() .

hasNext()로 다음 데이터가 있는지 확인 후, next()로 조회.

Collection 인터페이스에 정의된 iterator() 메서드를 사용하여 Iterator를 얻은 후, 주로 while문을 사용하여 조회한다. Iterator는 일회용이므로, 다 쓰고 나면 새로 얻어와야 한다.

Map은 Collection 인터페이스의 자손이 아니기 때문에 iterator() 메서드가 없어 사용하지 못한다. 이 경우, keySet(), entrySet(), values() 등의 메서드를 이용하여 key와 value를 Set이나 다른 Collection으로 변환한 후 호출한다.


6. Arrays

배열을 다루는 메서드들이 정의된 클래스. 모두 static 메서드이다.

6-1. copyOf() / copyOfRange()

배열 복사. 새로운 배열을 생성하여 반환한다.

6-2. fill(), setAll()

배열 채우기. setAll()은 배열을 채우는 데 사용할 함수형 인터페이스를 매개변수로 받는다.

6-3. sort(), binarySearch()

배열 정렬과 이진탐색.

binarySearch() 는 반드시 sort() 를 사용하여 배열을 정렬한 후 사용해야 올바른 결과를 얻을 수 있다.

6-4. equals(), toString()

배열 비교와 출력.

3차원 이상의 다차원 배열은 deepEquals()와 deepToString()을 사용하여 비교해야 한다.

6-5. asList(Object... a)

List로 배열 변환. 가변 매개변수로, 매개변수의 개수가 지정되어 있지 않다.

List는 읽기 전용이어서 크기를 변경할 수 없으므로, 추가/삭제 등의 변경 작업을 위해서는 ArrayList 생성자를 이용한다.


7. Comparable / Comparator

객체 정렬에 필요한 메서드를 정의한 인터페이스.(정렬 기준 제공)

Comparable은 기본 정렬기준을 구현하는 데 사용하므로, 그 외 다른 기준으로 정렬하고 싶으면 Comparator를 사용한다.

public interface Comparable {
  int compareTo(Object o); // 객체 자신(this)과 o를 비교
}

public interface Comparator {
  int compare(Object o1, Object o2); // o1과 o2를 비교
  boolean equals(Object obj);
}

비교했을 때 결과는 다음과 같다:

  • 비교하는 두 객체가 같으면 0
  • 비교하는 값보다 작으면 음수 / 크면 양수

8. Collections 클래스

컬렉션을 위한 유용한 메서드를 제공(모두 static 메서드)

8-1. 컬렉션 동기화 - synchronizedXXX()

static Collection synchronizedCollection(Collection c)
static List synchronizedList(List list)
static Set synchronizedSet(Set s)
static Map synchronizedMap(Map m)
static SortedSet synchronizedSortedSet(SortedSet ss)
static SortedMap synchronizedSortedMap(SortedMap sm)
List syncList = Collections.synchronizedList(new ArrayList(...));

매개변수로 동기화되지 않은 컬렉션을 넣어서 동기화된 컬렉션을 만든다.

8-2. 변경불가(read-only) 컬렉션 만들기 - unmodifiableXXX()

컬렉션이 변경되지 않도록 보호해야 할 때 사용한다.

8-3. 싱글톤 컬렉션 만들기 - singletonXXX()

static List singletonList(Object o)
static Set singleton(Object o) // singletonSet이 아님!!
static Map singletonMap(Object key, Object value)

객체 1개만 저장할 수 있는 컬렉션을 만들 때 사용한다.

8-4. 한 종류의 객체만 저장하는 컬렉션 만들기 - checkedXXX()

지정한 한가지 타입만 저장이 가능한 컬렉션을 만들 때 사용한다.

지네릭스가 나오기 이전( JDK 1.5 이전 )에는 checkedXXX() 메서드를 이용하여 한가지 타입만 저장이 가능하도록 했음.

0개의 댓글