본문 바로가기
java

Java | 컬렉션 프레임워크

by 좋으네요 2023. 2. 2.
728x90

자바 컬렉션 프레임워크란?

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

 

컬렉션 프레임워크는 몇 가지 인터페이스를 통해서 다양항 컬렉션 클래스를 이용할 수 있도록 설계되어 있다.

→ 주요 인터페이스로는 List, Set, Map이 있다.

→ List와 Set은 객체를 추가, 삭제, 검색하는 방법에 있어서 공통점이 있기 때문에 공통된 메소드만 따로 모아 Collection 인터페이스로
    정의해두고 이것을 상속하고 있다.

→Map은 키와 값을 하나의 쌍으로 묶어서 관리하는 구조로 되어 있어 사용방법이 다르다.

 

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

 

 


List 컬렉션

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

메소드는 인덱스를 매개값으로 갖는 메소드들이 많다(책 참고)

  • ArrayList
    • List 컬렉션에서 가장 많이 사용하는 컬렉션이다. ArraryList에 객체를 추가하면 내부배열에 객체가 저장된다. 일반 배열과 차이점은 제한 없이 객체를 추가할 수 있다는 것이다.
    • List컬렉션은 객체 자체를 저장하는 것이 아니라 객체의 번지를 저장, 동일한 객체를 중복저장할 수 있는데 이 경우 동일한 번지가 저장되고 null 또한 저장 가능하다.
    • 컬렉션은 객체를 추가하면 인덱스 0번부터 차례대로 저장되고 삽입, 삭제 시 인덱스가 1씩 당겨지거나 밀려난다. 빈번한 객체 삭제와 삽입이 일어나는 곳에서는 ArrayList를 사용하는 것은 바람직하지 않으며 LinkedList를 사용하는 것이 좋다.
  • LinkedList
    • ArrayList와 사용방법은 동일하나 내부 구조는 완전히 다르다. ArrayList는 내부배열에 객체를 저장하지만 LinkedList는 인접 객체를 체인처럼 연결해서 관리한다.
  • Vector
    • ArrayList와 동일한 내부 구조를 가지고 있고 차이점은 Vector는 동기화된 메소드로 구성되어 있어 멀티 스레드가 동시에 Vector()메소드를 실행할 수 없다는 것 → 멀티 스레드 환경에서는 안전하게 객체를 추가, 삭제할 수 있다.

 


Set 컬렉션

→ List 컬렉션은 저장 순서를 유지하지만, Set 컬렉션은 저장 순서가 유지 되지 않고 중복해서 저장할 수 없다.

→ Set 컬렉션에는 HashSet, LinkedHashSet, TreeSet 등이 있다.

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

Set 컬렉션은 인덱스로 객체를 검색해서 가져오는 메소드가 없어 객체를 한 개씩 반복해서 가져와야 하는데 두 가지 방법이 있다.

//1. **for문 이용하기**
Set<E> set =new HashSet<>();
for(E e :set) {
...
}

//2. **Set 컬렉션의** Set<E> set =new HashSet<>();
Iterator<E> iterator = set.iterator();**() 메소드로 반복자를 얻어 객체를 하나씩 가져오기**
Set<E> set =new HashSet<>();
Iterator<E> iterator = set.iterator();

 


 

 

Map 컬렉션

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

→ 키와 값은 모두 객체이다.

→ 키는 중복저장할 수 없지만 값은 중복 저장할 수 있다.

→ 기존에 저장된 키와 동일한 키로 값을 저장하면 기존의 값은 없어지고 새로운 값으로 대치된다.

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

  • HashMap
    • 키로 사용할 객체가 hashCode() 메소드의 리터값이 값고 equals()메소드가 true를 리턴할 경우 동일키로 보고 중복 저장을 허용하지 않는다.
//HashMap 컬렉션을 생성하는 방법. K와 V는 각각 키와 값의 타입을 지정할 수 있는 타입 파라미터

Map<K, V> map = new HashMap<K, V>();
// K = 키타입 V = 값 타입

ex)
Map<String, Interger> map = new HashMap<String, Interger>();
//키는 String타입, 값은 Interger타입으로 값는 경우
Map<String, Interger> map = new HashMap<>();
//Map에 지정된 키와 값의 타입이 HashMap과 동일한 경우 HashMap<>을 사용할 수 있다.

Map map = new HashMap();
//모든 타입의 키와 객체를 저장할 수 있도록 HashMap를 다음과 같이 생성할 수 있지만 이런경우는 거의 없다.
  • Hashtable
    • HashMap과 동일한 내부 구조를 가지고 있다. 차이점은 동기화된 메소드로 구성되어 멀티 스레드가 동시에 Hashtable의 메소드들을 싱핼할 수 없다는 것이다 → 멀티 스레드 환경에서도 안전하게 객체를 추가, 삭제할 수 있다.
  • Properties
    • Properties는 Hashtable의 자식 클래스이기 대문에 Hashtable의 특징을 그대로 가지고 있다. Properties는 키와 값을 String 타입으로 제한한 컬렉션이다.
    • Properties는 주로 확장자가 .properties인 프로퍼티 파일을 읽을 때 사용한다. 프로퍼티파일은 다음과 같이 키와 값이 = 기호로 연결되어 있는 텍스트 파일이다.
    • 객체생성 후 load()메소드로 프로퍼디 파일의 내용을 메모리로 로드해 프로퍼티 파일의 내용을 코드에서 쉽게 읽을 수 있다.
//database.properties 프로퍼티 파일의 내용 읽어오기

Properties properties = new Propertiess();
properties.load(Xxxclass.getResourceAsStream("database.properties"));

//getResourceAsStream()메소드는 주어진 상대 경로의 리소스 파일을 읽는 InputStream을 리턴한다.

 


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

→ TreeSet, TreeMap이 있음

 

TreeSet

→ Set 컬렉션이다.

→ 루트노트라고 불리는 하나의 노드에서 시작해 각 노드에 최대 2개의 노드를 연결할 수 있는 구조를 가지고 있다.

→ TreeSet에 객체를 저장하면 부모노드의 객체와 비교애 낮은 것은 왼쪽 자식노드에, 높은것은 오른쪽 자식 노드에 저장한다.

→ TreeSet에만 정의되어 있는 검색 관련 메소드가 있다.

 

TreeMap

→ Map 컬렉션이다.

→ TreeSet과 차이점은 키와 값이 저장된 Entry를 저장한다는 점이다.

→ 엔트리를 저장하면 키를 기준으로 자동정렬되는데 부모 키 값과 비교해 낮은 것은 왼쪽, 높은것은 오른쪽 자식

 노드 Entry객체를 저장한다.

→ TreeMap에만 정의되어 있는 검색 관련 메소드가 있다.

 


 

LIFO와 FIFO 컬렉션

LIFO

후입선출: 나중에 넣은 객체가 먼저 빠져나가는 구조

FIFO

선입선출: 먼저 넣은 객체가 먼저 빠져나가는 구조

컬렉션프레임워크는 LIFO자료구조를 제공하는 스택클래스와 FIFO 자료구조를 제공하는 큐 인터페이스를 제공하고 있다.

→ 스택을 응용한 대표적인 예가 JVM 스택 메모리

→ 큐를 응용한 대표적인 예가 스레드풀의 작업 큐이다.

 


 

동기화된 컬렉션

→ 컬렉션 프레임워크 대부분의 클래스들은 싱글 스레드 환경에서 사용할 수 있도록 설계되어 여러 스레드가 동시에 컬렉션에 접근한다면 의도하지 않게 요소가 변경될 수 있는 불안전한 상태가 된다.

→ ArrayList, HashSet, HashMap은 동기화된 메소드로 구성되지 않아 멀티 스레드 환경에서 안전하지 않지만 경우에 따라 멀티 스레드 환경에서 사용하고 싶을 때를 대비 컬렉션 프레임워크는 비동기화된 메소드를 동기화된 메소드로 래핑하는 Collection synchronizedXXX()메소드를 제공한다. 이 메소드들은 매개값으로 비동기화된 컬렉션을 대입하면 동기화된 컬렉션을 리턴한다.

리턴타입 메소드(매개변수) 설명

List<T> synchronizedList(List<T>list) List를 동기화된 List로 리턴
Map<K,V> synchronizedMap(Map<K,V>m) Map를 동기화된 Map으로 리턴
Set<T> synchronizedSet(Set<T>s) Set를 동기화된 Set으로 리턴

 


 

수정할 수 없는 컬렉션

→ 요소를 추가, 삭제할 수 없는 컬렉션

→ 컬렉션 생성 시 저장된 요소를 변경하고 싶지 않을 때 유용

//수정할 수 없는 컬렉션 만드는 3가지 방법

//1. List, Set, Map 인터페이스의 정적 메소드인 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. List, Set, Map 인터페이스의 정적 메소드인 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. 배열로 생성
String[] arr = { "A", "B", "C"};
List<String> immutableList = Arrays.asList(arr);

 

 

'java' 카테고리의 다른 글

Java | 제네릭  (0) 2023.02.06
Java | 람다식  (1) 2023.02.02
[java] 중첩 클래스  (0) 2023.02.01