[1일1쓰기] Day 25 - 15장. 컬렉션

Ki Tae Park·2021년 8월 7일
0

자바

목록 보기
13/13

15.1 컬렉션 프레임워크 소개

다수의 객체를 저장해서 사용하려면?

배열을 사용하면 되지만 크기를 미리 지정해줘야 되고, 엄청 크게 미리 잡아놓는다고 해도 완전한 해결책은 아니다.

자바는 자료구조를 활용한 컬렉션 프레임워크를 통해 배열의 한계점을 극복하고 객체들을 효율적으로 저장, 삭제, 수정할 수 있도록 여러 인터페이스와 클래스들을 포함시켰는데 주로 사용되는 인터페이스는 List, Set, Map이 있다. 해당 인터페이스들은 컬렉션을 사용하는 방법을 정의해놓았으며 다음은 인터페이스로부터 사용 가능한 컬렉션 클래스 목록이다.

  • List
    • ArrayList
    • Vector
    • LinkedList
  • Set
    • HashSet
    • TreeSet
  • Map
    • HashMap
    • Hashtable
    • TreeMap
    • Properties

15.2 List 컬렉션

List 컬렉션은 객체 자체를 저장하는 것이 아닌 객체의 번지를 저장하여 해당 객체를 참조한다.

15.2.1 ArrayList

데이터를 추가하면 인덱스로 관리한다는 점에서 일반 배열과 유사하지만 가장 큰 차이점으론 크기 변경이다. 배열은 사용 중에 배열 크기를 변경할 수 없고 고정된다. 하지만 ArrayList는 용량이 넘치게 될 경우 자동으로 저장 용량이 늘어난다.

ArrayList는 특정 인덱스의 객체가 삭제되는 경우 이후 인덱스들이 앞으로 당겨진다. 따라서 객체의 삭제와 삽입이 빈번하게 일어나는 경우 ArrayList 보단 LinkedList를 사용하는 것이 좋다. 그러나 인덱스 검색이나 맨 마지막에 객체를 추가하는 경우 ArrayList가 좋은 성능을 발휘한다.

15.2.2 Vector

ArrayList와 동일한 내부 구조를 가지고 있다. ArrayList와 다른 점은 Vector는 동기화된 메소드로 구성되어 있기 때문에 멀티 스레드가 동시에 이 메소드들을 실행할 수 없다. 그러므로 하나의 스레드가 실행을 완료해야만 다른 스레드를 실행할 수 있다. 그 결과 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제할 수 있다. 이를 Thread Safe 하다 고 한다.

15.2.3 LinkedList

ArrayList와 사용 방법은 똑같지만 내부 구조는 완전히 다르다. ArrayList는 내부 배열에 객체를 인덱스로 관리하지만 LinkedList는 인접 참조를 링크해서 체인처럼 관리한다. 인접한 객체의 주소값을 참조하는 방식으로 연결이 된다.

LinkedList에선 특정 인덱스의 객체를 삭제하면 앞뒤 링크만 변경되고 나머지 링크는 변경되지 않는다.

15.3 Set 컬렉션

List 컬렉션은 순서를 유지하지만 Set 컬렉션은 순서를 유지하지 않는다. 또한 중복해서 저장할 수 없고 하나의 null 만을 저장할 수 있다.

Set 컬렉션은 인덱스로 객체를 검색해서 가져오지 않는다. 그 대신 Iterator 를 통해 객체를 가져온다. Iterator (반복자)는 Iterator 인터페이스르르 구현한 객체를 의미하고 iterator 메소드를 호출하면 얻을 수 있다.

15.3.1 HashSet

HashSet은 Set 인터페이스의 구현 클래스이다. 다음과 같이 선언해서 사용할 수 있다.

Set<E> set = new HashSet<E>();

15.4 Map 컬렉션

Map 컬렉션은 키와 값으로 구성된 Entry 객체를 저장하는 구조를 가지고 있다. 키와 값은 모두 객체이다. 키는 중복되서 저장될 수 없지만 값은 중복되서 저장될 수 있다.

Map 컬렉션에는 HashMap, Hashtable, LinkedHashMap, Properties, TreeMap 등이 있다.

15.4.1 HashMap

15.4.2 HashTable

15.4.3 Properties

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

15.5.1 이진 트리 구조

이진 트리는 부모 노드의 값보다 작은 노드는 왼쪽에, 큰 노드는 오른쪽에 위치시킴

문자를 비교할 경우 문자의 유니코드 값으로 비교한다.

15.5.2 TreeSet

TreeSet은 이진 트리를 기반으로한 Set 컬렉션이다. 하나의 노드는 노드값인 value와 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두 개의 변수로 구성된다. TreeSet에 객체를 저장하면 자동 정렬됨.

TreeSet treeSet = new TreeSet();

위에서 반환 형식을 Set 인터페이스 타입 변수로 할수도 있지만 위와 같이 한 이유는 객체를 찾거나 범위 검색과 관련된 메소드를 쓰기 위해서다.

15.5.3 TreeMap

이진트리를 기반으로 한 Map 컬렉션. TreeSet과 차이점은 키와 값이 저장된 Map.Entry를 저장한다는 점. TreeMap에 객체를 저장하면 자동 정렬됨.

TreeMap<K, V> treeMap = new TreeMap<K, V>();

15.5.4 Comparable과 Comparator

TreeSet과 TreeMap은 정렬을 위해 java.lang.Comparable을 구현한 객체를 요구한다(Integer, String, Double은 Comparable 인터페이스를 구현함). 그러므로 사용자 정의 클래스도 Comparable을 구현하면 자동 정렬이 가능하다. compareTo 메소드를 오버라이딩 하여 int 형식의 리턴값을 만들어야 함.

물론 위와 같이 Comparable을 구현하지 않은 비구현 객체 Key를 정렬할 방법도 존재하는데 TreeSet과 TreeMap의 매개값으로 Comparator 를 넘겨주면 된다.

compare 메소드를 오버라이딩하여 int 형식의 리턴값을 넘겨주면 됨.

15.6 LIFO와 FIFO 컬렉션

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

15.6.1 Stack

15.6.2 Queue

15.7 동기화된 컬렉션

컬렉션 프레임워크의 대부분 클래스들은 싱글 스레드 환경에서 사용할 수 있도록 설계됨..그렇기 때문에 여러 스레드가 동시에 컬렉션에 접근하면 의도하지 않게 요소가 변경될 수 있는 불안전한 상태가 된다. (뭐지..싱글스레드 라고 하니 컬렉션의 처리방식에서 자바스크립트가 자꾸 연상이 된다..)

멀티 스레드 환경에서 안전하게 요소 처리 가능: Vector - Hashtable

안전하지 않은 것들: ArrayList, HashSet, HashMap (동기화된 메소드로 구성되어 있지 않으므로 멀티스레드 환경에 적합하지 않음)

따라서 필요에 따라 ArrayList 등을 멀티 스레드 환경으로 전달할 필요가 생기고 이러한 경우를 대비, 컬렉션 프레임워크는 비동기화된 메소드를 동기화된 메소드로 래핑하는 Collections의 synchronizedXXX() 메소드를 제공한다. 매개값으로 비동기화된 컬렉션을 대입하면 동기화된 컬렉션을 리턴한다.

15.8 병렬 처리를 위한 컬렉션

동기화된 컬렉션은 멀티 스레드 환경에서 하나의 스레드가 요소를 안전하게 처리하도록 도와주지만 전체 요소를 빠르게 처리하진 못한다. 왜냐면 하나의 스레드를 처리할 때 전체 잠금이 발생해 다른 스레드는 대기상태가 되기 때문이다. 그래서 병렬적으로 컬렉션 요소들을 처리할 수 없는데 자바는 멀티 스레드가 컬렉션 요소를 병렬적으로 처리할 수 있는 특별한 컬렉션을 제공한다.

  • ConcurrentHashMap

    • 부분 잠금을 사용함, 즉 처리하는 요소만 부분 잠금하고 나머지는 다른 스레드가 변경할 수 있도록 함

    • Map 인터페이스 메소드를 호출하여 사용

      Map<K, V> map = new ConcurrentHashMap<K,V>();
  • ConcurrentLinkedQueue

    • 락-프리 알고리즘을 구현한 컬렉션.

    • 여러 개의 스레드가 동시에 접근할 경우 잠금을 사용하지 않아도 최소 하나의 스레드가 안전하게 요소를 저장하거나 얻을 수 있게 해줌.

    • Queue 인터페이스 메소드를 호출하여 사용

      Qeueu<E> queue = new ConcurrentLinkedQueue<E>();
profile
#Coder Became Developer

0개의 댓글