컬렉션 프레임워크와 Stream API - JCF의 필요성과 구조 이해

urur-27·2025년 2월 19일

StreamAPI

목록 보기
1/6

자바에서 데이터를 다룰 때 가장 먼저 배우는 구조가 배열(Array) 이다.
하지만 배열은 크기 제한, 기능 부족 등의 한계를 가지므로, 자바에서는 JCF(Java Collection Framework) 를 제공하여
보다 유연하고 효율적인 데이터 관리를 지원한다.

이 글에서는 배열의 한계를 살펴보고, JCF의 기본 구조와 활용법을 학습하여
효율적인 데이터 처리를 위한 방법을 알아본다.


1. 배열의 한계와 컬렉션의 필요성

1.1 배열의 한계

  • 고정 크기
    배열을 생성할 때 크기를 확정해야 하며, 실행 중 크기 변경이 불가능하다.
    크기를 변경하려면 새로운 배열을 생성하고 기존 데이터를 복사해야 한다.
  • 한정된 기능
    삽입, 삭제, 탐색 시 수동으로 인덱스를 관리해야 한다.
    요소 추가/삭제 시, 배열을 직접 재정렬해야 하므로 코드가 복잡해질 수 있다.
  • 타입 안정성 문제
    자바에서 배열은 런타임 시 타입 오류가 발생할 가능성이 있다.
    (ex: Object[] objArr = new String[5]; objArr[0] = 10; // 컴파일 통과, 실행 시 오류 발생)

1.2 컬렉션(Collection)의 필요성

자바 컬렉션 프레임워크(JCF)는 배열의 한계를 극복하기 위해 제공되며, 다음과 같은 장점을 갖는다.

  • 동적 크기 관리
    List 계열 등 컬렉션은 내부적으로 동적 배열 또는 노드 연결 방식을 사용하여, 요소 추가 시 자동으로 크기가 확장된다
  • 풍부한 유틸리티 메서드
    삽입, 삭제, 검색, 정렬 등 자주 사용하는 기능들이 미리 제공되므로, 개발자는 핵심 로직에 집중할 수 있다.
  • 제너릭 활용
    제네릭 기반의 컬렉션을 선언하면, 타입 안정성을 확보할 수 있다.
    컴파일 시점에 타입을 체크하므로 런타임 오류를 방지하고 코드 가독성을 향상시킨다.

1.3 배열과 ArrayList 비교 예시

배열을 사용할 때 크기가 부족하면 재할당과 복사가 필요하지만,
ArrayList 같은 컬렉션은 내부적으로 동적 배열을 사용하여 자동 확장된다.

배열 사용 예시

int[] numbers = new int[3];
numbers[0] = 10;
numbers[1] = 20;
numbers[2] = 30;

// 여기서 추가 데이터를 넣으려면 새로운 배열을 만들어 복사해야 한다.
int[] newNumbers = new int[5];
System.arraycopy(numbers, 0, newNumbers, 0, numbers.length);
newNumbers[3] = 40;

ArrayList 사용

import java.util.ArrayList;
import java.util.List;

List<Integer> numberList = new ArrayList<>();
numberList.add(10);
numberList.add(20);
numberList.add(30);
numberList.add(40);  // 크기를 별도의 설정 없이도 자동 확장

배열을 사용할 때는 크기가 부족하면 재할당과 복사를 거쳐야 한다.
반면 ArrayList와 같은 컬렉션을 사용하면 내부적으로 동적 배열을 재할당하므로, 단순히 add() 메서드를 호출하기만 해도 확장할 수 있다.


2. JCF(Java Collection Framework)의 기본 구조

2.1 Collection 계열

Collection 인터페이스는 모든 컬렉션의 공통 기능을 정의한 최상위 인터페이스
요소들을 그룹으로 취급하기 위한 공통 기능( add(), remove(0, size() 등)을 정의한다.
이 인터페이스를 확장하여 List, Set 등의 자료구조가 구현된다.

  • List 인터페이스
    순서가 있는 데이터 구조이며, 인덱스를 통해 요소를 관리한다.
    중복을 허용한다.
    대표 구현체: ArrayList, LinkedList, Vector 등
  • Set 인터페이스
    중복을 허용하지 않는 집합 자료구조
    요소의 중복 여부를 hashCode() 및 equals() 메서드를 이용하여 판단한다.
    대표 구현체: HashSet, LinkedHashSet, TreeSet 등

2.2 Map 계열

Map은 Collection 인터페이스를 상속받지 않지만, JCF에서 함께 관리하는 자료구조이다.

  • Map 인터페이스
    Key-Value 쌍으로 데이터를 저장하는 구조
    Key는 중복 불가, Value는 중복 가능
    대표 구현체: HashMap, LinkedHashMap, TreeMap

2.3 JCP 계층 구조 개념도

          Collection
          /   |   \
       List  Set   ...
     /     \
ArrayList   LinkedList

          Map
         /   \
     HashMap  ...

2. 4 JCF의 특징과 장점

JCF는 단순한 자료구조 라이브러리가 아니라, 유연하고 강력한 데이터 처리 도구이다.
이를 가능하게 하는 몇 가지 핵심 특징이 있다.

  1. 표준화된 인터페이스
    List, Set, Map 같은 상위 인터페이스가 존재하므로,
    구현체 교체가 용이하며 코드 변경 범위가 최소화된다.

  2. 다양한 구현체 제공
    삽입/삭제 빈도, 탐색 빈도, 정렬 필요성 등에 따라
    최적의 자료구조를 선택할 수 있다.
    빠른 탐색이 필요하면 → HashMap, ArrayList
    잦은 삽입/삭제가 필요하면 → LinkedList
    정렬이 필요하면 → TreeSet, TreeMap

  3. 제네릭(Generic)으로 타입 안정성 확보
    컴파일 시 타입 체크를 수행하므로 런타임 오류를 줄이고 코드 가독성을 높인다.

    List<String> names = new ArrayList<>();
    names.add("Alice");
    names.add(123);  // 컴파일 오류 발생 (제네릭 적용 덕분)
  4. 강력한 유틸리티 기능
    Collections 클래스에서 정렬, 최소/최대값 탐색, 필터링 등의 기능을 제공하여
    복잡한 연산을 간편하게 수행할 수 있다.

import java.util.*;

List<Integer> list = Arrays.asList(3, 1, 4, 1, 5, 9);
Collections.sort(list);
System.out.println(list); // [1, 1, 3, 4, 5, 9]

3. 정리

배열은 크기 제한, 기능 부족 등의 단점이 있어 실무에서는 JCF를 활용하는 것이 일반적이다.
JCF는 Collection 계열(List, Set)과 Map 계열로 나뉘며, 다양한 구현체를 제공한다.
JCF를 활용하면 동적 크기 관리, 유틸리티 제공, 제네릭 활용, 표준 인터페이스 등의 장점을 얻을 수 있다.
자료구조의 특성과 목적을 고려하여 적절한 컬렉션을 선택하는 것이 중요하다.

profile
끄아악

0개의 댓글