본문 바로가기
Study/Language

[Java] 컬렉션 프레임워크를 알아보자

by jamiehun 2023. 4. 19.

<이것이 자바다>를 요약 정리한 글입니다.

문제가 될 시 글을 내리도록 하겠습니다.

 


1. 컬렉션 프레임워크란?

자료구조를 바탕으로 객체들을 효율적으로 추가, 삭제 , 검색할 수 있도록 인터페이스와 클래스들을

java.util 패키지에 포함시켜놓은 것이다.

 

크게 3가지가 있는데 List, Set, Map이 그것이다.

 

List는

순서를 유지하고 저장하며, 중복저장이 가능하다. 대표적으로 ArrayList, Vector, LinkedList가 있다.

 

Set은

순서를 유지하지않고 저장하며 중복 저장이 불가능하다. 대표적으로 HashSet, LinkedHashSet, TreeSet이 있다.

 

Map은

키와 값으로 구성된 엔트리를 저장한다. 키는 중복 저장되지 않는다. 대표적으로 HashMap, HashTable, LinkedHashMap 등이 있다.

 

2. List 컬렉션

List 컬렉션의 특징으로는

객체를 인덱스로 관리한다. 즉, 객체 저장시 인덱스 부여되고 인덱스로 객체를 검색, 삭제할 수 있다.

 

메서드들을 간단하게 살펴보면,

  • 추가 : add(e) / add(index, e) / set(index, e)
  • 검색 : contains() / get(index) / isEmpty() / size()
  • 삭제 : clear() / remove(index) / remove(object)

ArrayList

ArrayList는 

일반 배열과는 다르게 제한 없이 객체를 추가할 수 있다.

객체 자체를 저장하는 것이 아니라 객체의 번지를 저장하는데, 이는 즉 object를 저장한다는 것이다.

 

동일한 객체를 중복 저장할 수 있는데, 이 경우 동일한 번지가 저장된다.

빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList를 사용하는 것이 적합하지 않고 LinkedList가 적합하다.

 

객체 생성 방법은 아래와 같다.

 

List<E> list = new ArrayList<E>(); // E에 지정된 타입의 객체만 저장

List<E> list = new ArrayList<>();   // E에 지정된 타입의 객체만 저장

List list = new ArrayList();               // 모든 타입의 객체를 저장

Vector

Vector는 ArrayList와 거의 유사하지만 다른 점은 동기화된 메서드로 구성되어 있기 때문에 멀티스레드가 동시에 Vector() 메서드를 실행할 수 없다. 즉, 멀티 스레드 환경에서 안전하게 객체를 추가 또는 삭제할 수 있다.

 

객체 생성 방법은 아래와 같다.

 

List<E> list = new Vector<E>(); // E에 지정된 타입의 객체만 저장

List<E> list = new Vector<>();   // E에 지정된 타입의 객체만 저장

List list = new Vector();                // 모든 타입의 객체를 저장

 

LinkedList

 

ArrayList는 내부 배열에 객체를 저장하지만, LinkedList는 인접 객체를 체인처럼 연결해서 관리한다.

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

 

객체 생성 방법은 아래와 같다.

 

List<E> list = new LinkedList<E>(); // E에 지정된 타입의 객체만 지정

List<E> list = new LinkedList<>();   // E에 지정된 타입의 객체만 지정

List list = new LinkedList();               // 모든 타입의 객체를 저장

 

3. Set 컬렉션

Set 컬렉션의 특징으로는

List 컬렉션은 저장순서를 유지하지만 Set 컬렉션은 저장순서가 유지되지 않는다. 

또한 객체를 중복해서 저장할 수 없기 때문에 수학의 set과 비슷하다고 볼 수 있다.

List와 다르게 인덱스로 객체를 검색해서 가져오는 메서드가 따로 없다.

 

메서드들을 간단하게 살펴보면 아래와 같다.

  • 추가 : add(e)
  • 검색 : contains(Object o) / isEmpty() / iterator() / size()
  • 삭제 : clear() / remove(Object o)

반복문으로 객체를 가져올 때는 아래와 같은 방법을 사용한다.

 

1) for 문 이용

Set<E> set = new HashSet<>();
for(E e : set){
	... }

 

2) iterator() 메서드 이용

Set<E> set = new HashSet<>();
Iterator<E> iterator = set.iterator();

while(iterator.hasNext()){
	E e = iterator.next();
}

HashSet

HashSet은

Set 컬렉션 중 가장 많이 사용되는 것으로 동일한 객체 (동등 객체)는 중복저장하지 않는다.

다른 객체라도 hashCode() 메서드의 리턴값이 같고 equals() 메서드가 true 리턴 시 동일한 객체라고 판단하고 중복저장하지 않는다.

반대로 다른 객체라도 hashCode() 메서드의 리턴값이 같고 equals() 메서드가 true 리턴 시 동일한 객체라고 판단하고 중복저장하지 않는다.

 

객체 생성 방법은 아래와 같다.

 

Set<E> set = new HashSet<E>(); // E에 지정된 타입의 객체만 저장

Set<E> set = new HashSet<>();   // E에 지정된 타입의 객체만 저장

Set set = new HashSet();               // 모든 타입의 객체를 저장

 

4. Map 컬렉션

Map 컬렉션의 특징으로는

key와 value 값으로 구성된 엔트리 객체를 저장한다.

키는 중복 저장 불가능하나 값은 중복 저장 가능하다.

대표적으로 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다.

 

키를 매개값으로 갖는 메소드가 많다.

간단하게 메소드들을 살펴보면 

  • 추가 : V put(K key, V value)
  • 검색 : containsKey(Object key) / containsValue(Object Value) / Set<Map.Entry<K, V>> entrySet() / V get(Object key) / boolean isEmpty() / Set<K> keySet() / int size() / Collection<V> values()
  • 삭제 : void clear() / V remove(Object key)

HashMap

HashMap은 Map 컬렉션에서 많이 쓰이는 것 중 하나인데,

아래와 같이 객체를 생성한다.

 

Map<K, V> map = new HashMap<K, V>();

Map<String, Integer> map = new HashMap<String, Integer>();

Map<String, Integer> map = new HashMap<>();

Map map = new HashMap(); -> 해당 경우도 가능은 하지만, 거의 쓰지 않는다.

 

여기서 궁금했던 점이 왜 

HashMap<K, V> map = new HashMap<K, V>(); 냐는 점인데,

그건 Map의 경우 인터페이스고 HashMap이 구현체이기 때문이다. 

 

공식문서를 살펴보면 아래와 같이 명확하게 기술되어 있다.

(위의 List와 Set도 마찬가지 일 것이다.)

 

Map

public interface Map<K, V>

- An object that maps keys to values

- A map cannot contain duplicate keys

- to take the place of the dictionary class (such as Hash map)

 

HashMap

Class HashMap<K, V>

- based implementation of the Map interface

- provides all the operational map operations

- No guarantees as to the order of the map 

Hashtable, Properties, TreeSet, NavigableSet

그 외에도 동기화된 메서드로 구현된 Hashtable,

properties 파일을 읽을 때 사용되는 Hashtable의 자식 클래스인 Properties,

이진트리를 기반으로 검색기능이 강화된 TreeSet 및 NavigableSet 등이 있다.

 

5. 기타 참고 사항

Comparable, Comparator

TreeSet에 저장되는 객체와 TreeMap에 저장되는 키 객체는 저장과 동시에 오름차순으로 정렬되어야하는데,

객체가 Comparable 인터페이스를 구현하고 있어야 가능하다. (Integer, Double, String 등)

 

Comparable 인터페이스의 경우,

compareTo() 메서드를 정의하며, 이 메서드 재정의하여 비교결과 정수값으로 리턴한다.

 

Comparator 인터페이스의 경우,

compare() 메서드를 정의하며, 비교 결과를 정수값으로 리턴한다.

Stack, Queue 컬렉션

Java에도 당연히 Stack과 Queue가 있다.

 

Stack 컬렉션의 경우 아래와 같이 생성한다. (삽입은 Push, 삭제는 Pop)

 

Stack<E> stack = new Stack<E>();

Stack<E> stack = new Stack<>();

 

Queue 컬렉션의 경우 아래와 같이 생성한다. (삽입은 Offer, 삭제는 Poll)

Queue 인터페이스를 구현한 대표적인 클래스는 LinkedList 이다.

 

Queue<E> queue = new LinkedList<E>();

Queue<E> queue = new LinkedList<>();

동기화된 컬렉션 

synchronizedXXX() 메서드를 통해 동기화된 컬렉션 사용 가능하다. (멀티 스레드 환경에서 안전하게 작동한다.)

수정할 수 없는 컬렉션

1) 정적 메서드 of() 사용

List<E> immutableList = List.of(E… elements);

Set<E> immutableSet = Set.of(E… elements);

Map<K, V> immutableMap = Map.of(K k1, V v1, K k2, V v2,…)

 

2) copyOf() 이용

List<E> immutableList = List.copyOf(Collection<E> coll);

Set<E> immutableSet = Set.copyOf(Collection<E> coll);

Map<K, V> immutableMap = Map.copyOf(Map<K, V> map);

 

3) 배열로 부터 수정할 수 없는 List 컬렉션 생성

String[] arr = {”A”, “B”, “C”}

List<String> immutableList = Arrays.asList(arr);