컬렉션 프레임워크
- 다수의 객체를 저장해 두고 필요할 때마다 꺼내서 사용하는 경우 효율적인 사용법 필요 ⇒ 배열 이용
- 배열은 쉽게 생성할 수 있지만 저장할 수 있는 객체 수가 배열 생성 시 결정
- 불특정 다수 객체 저장하기에 문제
- 객체 삭제 시 해당 인덱스가 비게 됨
- 자료 구조 사용
- 컬렉션 프레임워크의 주요 인터페이스 ⇒ List, Set, Map
List 컬렉션
- 객체를 일렬로 늘어놓은 구조
- 객체를 인덱스로 관리하기 때문에 객체를 저장하면 자동 인덱스가 부여되고 인덱스로 검색, 삭제 기능 제공
- 동일한 객체 중복 저장 가능 ⇒ 동일한 번지 참조
- null 저장 가능 ⇒ 해당 인덱스 객체 참조하지 않음
ArrayList
- List 인터페이스의 구현 클래스
- 저장 용량을 초과한 객체들이 들어오면 자동적으로 저장 용량 늘어남
- 일반적으로 컬렉션에는 단일 종류의 객체들 저장 ⇒ 제네릭 도입하여 타입 파라미터로 저장할 객체 타입 지정해서 불필요한 타입 변환 제거
- 배열과 달리 삭제 시 인덱스가 당겨짐 ⇒ 빈번한 객체 삭제와 삽입이 일어나는 곳에서 사용하는 것 좋지 않음
- 인덱스 검색, 마지막 객체 추가하는 경우 좋은 성능 발휘
- 고정된 객체들로 List 생성
List<T> list = Arrays.asList(T…a);
Vector
- ArrayList와 동일한 내부 구조
- 생성 : 저장할 객체 타입을 타입 파라미터로 표기하고 기본 생성자 호출
List<E> list = new Vector<E>();
- ArrayList와 다른 점
- Vector는 동기화된 메소드로 구성 ⇒ 멀티 스레드가 동시에 메소드들 실행 불가
- 멀티 스레드 환경에서 안전하게 객체를 추가, 삭제
LinkedList
- ArrayList와 사용 방법은 똑같지만 내부 구조 다름
- 인접 참조를 링크해서 체인처럼 관리
- 특정 인덱스의 객체 삭제, 삽입하면 앞뒤 링크만 변하고 나머지 링크 변경되지 않음 ⇒ 빈번한 객체 삭제, 삽입에서 더 좋은 성능 발휘
- 생성 : 저장할 객체 타입을 타입 파라미터에 표기하고 기본 생성자 호출
List<E> list = new LinkedList<E>;
Set 컬렉션
- 저장 순서가 유지되지 않음
- 객체 중복 저장 불가
- 하나의 null만 저장
- 인덱스로 객체를 검색해서 가져오는 메소드 없음 ⇒ 전체 객체를 대상으로 한번씩 반복해서 가져오는 반복자 제공
HashSet
- set 인터페이스의 구현 클래스
- 생성 : 기본 생성자 호출
Set<String> set = new HashSet<String>();
- 객체들을 순서 없이 저장, 동일한 객체 중복 저장하지 않음
- 동일한 객체
- hashCode() 메소드를 호출해서 해시코드 비교 ⇒ 동일한 해시코드 있으면 equals() 메소드로 객체 비교 ⇒ true면 중복 저장 하지 않음
Map 컬렉션
- 키와 값으로 구성된 Entry 객체를 저장하는 구조
- 키와 값은 모두 객체
- 키는 중복 저장 안되지만 값은 중복 저장 가능
HashMap
- Map 인터페이스를 구현한 대표적인 Map 컬렉션
- HashMap의 키로 사용할 객체는 hashCode() 와 equals() 메소드를 재정의해서 동등 객체가 될 조건을 정해야 함
- hashCode()가 같고 equals()가 true
- 키 값은 주로 String 사용
- 키, 값 타입 파라미터로 주고 기본 생성자 호출
Map<K, V> map = new HashMap<K, V>();
- 키, 값의 타입은 클래스 및 인터페이스만 가능
Hashtable
- HashMap과 동일한 내부 구조, 키 조건
- 동기화된 메소드로 구성 ⇒ 하나의 스레드가 실행 완료해야 다른 스레드를 실행할 수 있음
- 생성 방법 : 키, 값 타입 지정하고 기본 생성자 호출
Map<K, V> map = new Hashtable<K, V>();
Properties
- Hashtable의 하위 클래스 ⇒ Hashtable의 모든 특징을 그대로 갖고 있음
- 차이점 : 키와 값을 String 타입으로 제한한 컬렉션
- 애플리케이션 옵션 정보, 데이터베이스 연결 정보, 국제화 정보가 저장된 파일 읽을 때 주로 사용
- Properties 객체 생성 load() 메소드 호출
검색 기능 강화시킨 컬렉션
이진 트리 구조
- 여러 개의 노드가 트리 형태로 연결된 구조
- 루트 노드라고 불리는 하나의 노드에서부터 시작해 각 노드에 최대 2개의 노드를 연결할 수 있는 구조
- 부모 - 자식 관계(위가 부모, 아래가 자식)
- 부모 노드의 값보다 작은 노드는 왼쪽, 큰 노드는 오른쪽에 위치
TreeSet
- 이진 트리를 기반으로 한 Set 컬렉션
- 하나의 노드는 노드값인 value와 왼쪽과 오른쪽 자식 노드를 참조하기 위한 두 개의 변수로 구성
- 생성 : 저장할 객체 타입 파라미터로 표기하고 기본 생성자 호출
TreeSet<E> treeSet = new TreeSet<String>();
TreeMap
- 이진 트리를 기반으로 한 Map 컬렉션
- TreeSet과 차이점 : 키와 값이 저장된 Map.Entry 저장
- 객체 저장 시 자동 정렬 ⇒ 부모 키값과 비교해서 키 값이 낮은 것은 왼쪽 자식 노드, 높은 것은 오른쪽 자식 노드에 저장
- 생성 : 키, 값으로 저장할 객체 타입을 타입 파라미터로 주고 기본 생성자 호출
TreeMap<K, V> treeMap = new TreeMap<K, V>();
comparable, comparator
- TreeSet 객체와 TreeMap 키 자동 오름차순 정렬 ⇒ 숫자 타입은 값, 문자열 타입은 유니코드로 정렬
- TreeSet 객체와 TreeMap 키가 Comparable 구현하고 있지 않으면 저장하는 순간 ClassCastException 발생
- 생성자의 매개값으로 정렬자 제공하면 Comparable 비구현 객체도 정렬 가능
TreeSet<E> treeSet = new TreeSet<E>( new AscendingComparator() );
TreeMap<K, V> treeMap = new TreeMap<K, V>( new DescendingComparator() );
- comparator 인터페이스의 compare() 메소드 ⇒ 두 객체가 동등하면 0, 비교하는 값보다 앞에 오게 하려면 음수, 뒤로 가게 하려면 양수 리턴하도록 구현
LIFO, FIFO 컬렉션
- LIFO : 후입선출, 나중에 넣은 객체가 먼저 빠져나가는 자료구조 ⇒ 스택
Stack<E> stack = new Stack<E>();
- FIFO : 선입선출, 먼저 넣은 객체가 먼저 빠져나가는 자료구조 ⇒ 큐
Queue<E> queue = new LinkedList<E>();
동기화된 컬렉션
- 컬렉션 프레임워크의 대부분 클래스는 싱글 스레드 환경에서 사용할 수 있도록 설계
- 여러 스레드가 동시에 컬렉션에 접근하면 의도치 않게 요소가 변경될 수 있는 불안전한 상태
- ArrayList, HashSet, HashMap 멀티 스레드 환경에서 안전하지 않음
- 싱글 스레드 환경에서 사용하다 멀티 스레드 환경으로 전달
병렬 처리를 위한 컬렉션
- 동기화된 컬렉션은 멀티 스레드 환경에서 하나의 스레드가 요소를 안전하게 처리하게 도와줌 ⇒ 전체 요소를 빠르게 처리하지는 못함
- ConcurrentHashMap
- 부분 잠금 사용 ⇒ 전체 요소를 다 사용하지 못하도록 하지 않고 처리하는 요소가 포함된 부분만 잠금
- ConcurrentLinkedQueue 제공
- 락-프리(lock-free) 알고리즘 ⇒ 여러 개의 스레드가 동시에 접근할 경우, 잠금을 사용하지 않고도 최소한 하나의 스레드가 안전하게 요소를 저장하거나 얻도록 함