Java Collection Framework

갱갱갱갱
4 min read

컬렉션 프레임워크(Collection Framework)란?

자바에서 컬렉션 프레임워크란 다수의 데이터를 쉽고 효과적으로 처리할 수 있는 표준화된 방법을 제공하는 클래스와 인터페이스 집합입니다.

즉, 데이터를 저장하는 자료구조과 데이터를 처리하는 알고리즘을 구조화하여 클래스로 구현한 것입니다.

모든 컬렉션 프레임워크는 자바의 인터페이스를 기반으로 구현됩니다.


JFC(Java Collection Framework)의 도입 배경

JCF 이전에는 Arrays, Vector, Hashtable과 같은 클래스들이 존재했지만,

  • 공통 인터페이스가 없어 사용법이 제각각이었고,

  • 동일한 목적의 자료구조라도 메서드 명, 생성자, 사용 방식이 달라 혼란을 주었습니다.

또한, 기본 자료구조(List, Set, Map 등)는 프로젝트마다 반복적으로 직접 구현해야 했고, 이는 버그 발생 가능성과 성능 저하로 이어졌습니다.

이를 개선하기 위해 JCF는

  • 일관된 인터페이스 설계

  • 검증된 자료구조와 알고리즘 제공

  • 코드 재사용성 및 호환성 향상

    을 목표로 도입되었습니다.

참고: Vector나 Hashtable은 하위 호환성을 위해 여전히 존재하지만, 현재는 ArrayList나 HashMap과 같은 새로운 구현체 사용을 권장합니다.


컬렉션 프레임워크 주요 인터페이스

컬렉션 프레임워크에서는 데이터를 저장하는 자료구조에 따라 다음과 같은 핵심이 되는 주요 인터페이스를 정의하고 있습니다.

위의 그림에서 <E>나 <K,V>라는 것은 컬렉션 프레임워크를 구성하는 모든 클래스가 제네릭으로 표현되어 있음을 알려줍니다.

List 와 Set 인터페이스는 모두 Collection 인터페이스를 상속받지만, 구조상의 차이로 인해 Map 인터페이스는 별도로 정의됩니다.

자바 컬렉션 프레임워크의 주요 인터페이스에 대한 더 자세한 사항은 밑의 링크를 참고하면 됩니다.

Java Documentation : The Collections Framework =>

인터페이스설명대표 구현체
Collection데이터 그룹의 최상의 인터페이스List,Set,Queue
List순서 유지, 중복 허용ArrayList, LinkedList
Set중복 X, 순서 보장 XHastSet, TreeSet
QueueFIFO (선입선출)LinkedList, PriorityQueue
Mapkey-value 저장, 키 중복 XHashMap, TreeMap

주요 구현 클래스

  • List

    • ArrayList : 배열 기반, 조회 빠름, 삽입/삭제 느림

    • LinkedList : 노드 기반, 삽입/삭제 빠름, 조회 느림

  • Set

    • HashSet : 해시 기반, 순서 보장 X, 빠른 검색

    • TreeSet : 이진 검색 트리 기반, 정렬된 순서 유지

  • Map

    • HashMap : 키 해시 기반 저장, 빠른 검색

    • TreeMap : 키 정렬 유지, 범위 검색 가능


JFC 자료구조의 초기 용량을 지정하면 좋은 점

JFC 컬렉션은 내부적으로 배열이나 해시 테이블을 사용합니다.

만약 초기 용량을 지정하지 않으면, 데이터가 늘어날 때마다 자동으로 용량을 확장해야합니다.(배열 복사 또는 재해싱)

  • 초기 용량 지정 X → 데이터가 늘어날 때마다 여러 번 확장 작업 발생

  • 초기 용량 지정 O → 확장 작업 최소화, 성능 향상

  • ArrayList는 용량이 가득 차면 1.5배로 배열을 만들고 데이터를 복사함 → 빈번하면 성능 저하

  • HashMap은 용량이 가득 차면 2배 크리고 해시 테이블 재생성 및 재해싱 수행 → 비용 큼

  • 예측 가능한 데이터 크기일 때 미리 크기 설정하면 GC 부담도 줄어듦

// ArrayList의 초기 용량 지정
List<String> list = new ArrayList<>(1000);

// HashMap의 초기 용량 지정
Map<String, String> map = new HashMap<>(2000, 0.75f);

ArrayList에서의 예시 (MAX = 5,000,000)

  • ArrayList는 매개변수 없는 생성자 사용 시 초기에 내부 배열 크기는 0이지만, 처음 원소가 추가될 때 기본 용량 10으로 초기화됩니다.

  • 용량 증가 규칙 : (oldCapacity + oldCapacity >>1) → 1.5배 증가

  • 여러번의 리사이징이 일어날 경우, 새로운 배열을 만들고, 기존 데이터를 복사하는 과정이므로, CPU 비용 + 메모리 임시 사용량이 발생합니다.

  • 기본 생성자( new ArrayList<>() )

    • 10에서 시작 → 15→22 … 이런식으로 1.5배씩 증가

    • 5백만개를 담기 위해, 5백만을 초과하는 시점까지 계속 리사이징 진행

    • 마지막 증가 후 용량이 6,153,400까지 늘어날 수 있음.

    • 내부 배열 크기 x 4byte(참조) = 약 23.4MB (64bit JVM, 객체 헤더·패딩 고려 시 70MB 추정 가능)

  • 초기 용량 지정 (new ArrayList<>(MAX))

    • 5,000,000 크기의 배열 확보 → 리사이징 없음

    • 내부 배열 크기 x 4byte = 약 19MB → 불필요한 메모리 낭비와 리사이징 비용 방지


로드 팩터와 임계점

로드 팩터 (load factor)란 특정 크기의 자료구조에 데이터가 얼마나 차면 확장할지를 결정하는 비율입니다.

기본값 : 0.75

계산 방식 : 로드 팩터 = 저장된 엔트리 수 / 버킷 수

예를 들어 버킷이 100개이고, 로드 팩터가 0.75이면 75개가 차면 테이블을 확장한다는 뜻입니다.

임계점이란 해시 테이블이 확장되는 정확한 시점(엔트리 수) 입니다.

계산 방식 : 임계점 = 현재 용량 × 로드 팩터

  • 용량 16, 로드 팩터 0.75 → 임계점 12

  • 엔트리 개수가 12를 넘어가면 용량 32로 확장 후 재해싱

참고 자료 : http://www.tcpschool.com/java/java_collectionFramework_concept
https://steady-coding.tistory.com/354
https://www.maeil-mail.kr/question/235

0
Subscribe to my newsletter

Read articles from 갱갱 directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

갱갱
갱갱