[Java] 컬렉션 프레임워크 작성중

artp·2025년 2월 11일
0

java

목록 보기
15/31

10. 컬렉션 프레임워크

배열에 데이터를 삽입하거나 삭제하려면 직접 데이터를 이동시키는 코드를 작성해야 합니다. 그래서 데이터의 삽입이나 삭제가 쉽지 않습니다. 또한, 배열은 한 번 생성하면 크기가 고정됩니다. 저장 공간의 크기가 고정되므로 나중에 데이터를 추가하기도 어렵습니다.

이런 불편한 점을 개선하고 데이터를 더 효율적으로 조작하고 관리하기 위해 자바에서는 컬렉션을 제공합니다.
컬렉션데이터를 그룹으로 묶어 하나의 객체로 관리할 수 있게 하는 자료구조입니다. 컬렉션은 객체를 모아놓은 데이터 집합으로 그 자체도 객체입니다. 컬렉션의 종류로는 리스트(list), 집합(set), 맵(map), 큐(queue), 스택(stack) 등이 있습니다.

배열을 생성할 때 크기를 지정하면 크기를 변경할 수 없습니다. 배열이 가득 찼을 때 새로운 데이터를 저장하려면 더 큰 크기의 배열을 새로 생성하고 기존 데이터를 복사해야 합니다. 반면에 컬렉션은 동적 크기를 가집니다. 필요에 따라 크기를 자동으로 조절할 수 있으며, 데이터의 추가와 삭제도 쉽습니다.

배열같은 자료형의 데이터로 구성됩니다. 배열을 생성할 때 자료형을 지정해야 하고, 해당 자료형의 요소들만 저장할 수 있습니다. 반면에 컬렉션은 다양한 자료형을 지원하며 여러 타입의 객체를 담을 수 있습니다.

배열은 인덱스를 통해 접근할 수 있지만, 다른 기능은 거의 제공하지 않습니다. 추가, 삭제, 검색, 정렬 등을 작업하려면 직접 구현해야 합니다. 하지만 컬렉션은 데이터의 추가, 삭제, 검색, 정렬 등 다양한 기능의 메서드를 제공합니다. 그래서 데이터를 관리하기가 편합니다. 또한, 다양한 자료구조와 알고리즘이 이미 구현돼있어 사용자가 필요에 따라 선택해서 쉽게 사용할 수 있습니다.

자바에서는 컬렉션을 다루기 위해 컬렉션 프레임워크를 제공합니다. 컬렉션 프레임워크(Collection Framework)컬렉션을 효과적으로 사용하고 관리할 수 있도록 설계된 인터페이스와 클래스의 집합입니다. 컬렉션데이터의 집합을 나타내는 개념이라면 컬렉션 프레임워크컬렉션을 다루기 위해 설계한 코드 구조이자 도구라고 볼 수 있습니다. 컬렉션 프레임워크를 사용하면 다양한 컬렉션을 손쉽게 생성하고 수정 및 관리할 수 있습니다. 또한 자료구조의 구현을 신경 쓰지 않고 표준화된 구조를 이용해 일관된 방식으로 작업할 수 있게 도와줍니다.

10.1 컬렉션 프레임워크 개요

배열데이터를 저장하는 가장 기본적인 자료구조지만, 여러 한계가 있습니다.
한 번 크기가 정해지면 변경할 수 없으며, 데이터 삽입 및 삭제가 어렵고 기능이 제한적입니다.

이러한 문제를 해결하기 위해 자바에서는 컬렉션 프레임워크(Collection Framework)를 제공합니다.
컬렉션은 데이터를 그룹으로 묶어 효율적으로 관리하는 자료구조이며,
컬렉션 프레임워크는 컬렉션을 효과적으로 사용하기 위한 표준화된 인터페이스와 클래스의 집합입니다.

10.1.1 컬렉션과 컬렉션 프레임워크

1. 컬렉션(Collection)

컬렉션은 데이터를 그룹으로 묶어 저장하고 관리하는 자료구조입니다.
배열과 달리 크기를 동적으로 조절할 수 있고, 데이터 추가, 삭제, 검색 등의 기능을 기본적으로 제공합니다.

컬렉션의 대표적인 종류

  • List → 데이터의 순서를 유지하며, 중복을 허용하는 데이터 저장
  • Set → 데이터의 순서를 유지하지 않으며, 중복을 허용하지 않는 데이터 저장
  • Map → 키(Key)-값(Value) 형태로 저장, 키 중복 X

2. 컬렉션 프레임워크(Collection Framework)

컬렉션 프레임워크는 컬렉션을 표준화된 방식으로 사용하기 위해 설계된 인터페이스와 클래스의 집합입니다. 이를 통해 개발자는 자료구조 구현을 신경쓰지 않고, 이미 구현된 기능을 편리하게 활용할 수 있습니다.

10.1.2 컬렉션 프레임워크의 구조

컬렉션 프레임워크는 다양한 자료구조와 알고리즘을 표준화해 제공합니다. 컬렉션 프레임워크는 다음과 같이 리스트, 집합, 맵, 큐, 스택 등 자료구조표준화한 인터페이스들로 구성되어 있습니다.

1) Collection 인터페이스 (최상위 인터페이스)

컬렉션 프레임워크의 최상위 인터페이스로, 각 컬렉션의 공통된 동작을 정의합니다. Collection 인터페이스를 직접 구현한 클래스는 없습니다. 그대신 자식 인터페이스들이 이를 상속해 기능을 확장합니다.

2) List 인터페이스 (순서 유지, 중복 허용)

삽입된 순서대로 요소를 저장하는 리스트 컬렉션을 정의하는 인터페이스입니다. 중복 요소를 허용하며, 각 요소에는 인덱스로 접근할 수 있습니다. 주요 구현 클래스는 다음과 같습니다.

  • ArrayList: 배열로 구현된 클래스
  • LinkedList: 이중 연결 리스트로 구현된 클래스
  • Vector: ArrayList와 유사한 리스트이나 현재는 잘 사용하지 않음
  • Stack: Vector 클래스를 상속받아 구현된 클래스로 나중에 들어온 요소가 먼저 처리되는 LIFO(Last-In First-Out, 후입선출) 방식으로 요소를 관리함

3) Set 인터페이스 (순서 X, 중복 X)

순서를 보장하지 않으며, 중복 요소를 허용하지 않는 집합 컬렉션을 정의하는 인터페이스입니다. 주요 구현 클래스는 다음과 같습니다.

  • HashSet: 해시 테이블 구조로 구현된 집합
  • LinkedHashSet: HashSet의 변형 집합으로, 삽입된 순서를 유지
  • TreeSet: 이진 트리 구조로 구현된 집합으로, 요소가 정렬된 상태로 저장됨

4) Map 인터페이스 (키-값 저장, 키 중복 X)

키(Key)와 값(Value)을 한 쌍으로 저장하는 맵 컬렉션을 정의하는 인터페이스입니다. 키는 중복을 허용하지 않습니다. 주요 구현 클래스는 다음과 같습니다.

  • HashMap: 해시 테이블을 기반으로 구현된 클래스로, 키와 값의 순서가 보장되지 않음
  • LinkedHashMap: HashMap의 변형으로, 삽입된 순서를 유지함
  • TreeMap: 이진 트리 구조를 사용한 맵으로, 키를 기준으로 정렬됨

5) Queue 인터페이스

먼저 삽입된 요소가 먼저 처리되는 FIFO(First-In First-Out, 선입선출) 방식으로 요소를 관리하는 큐 컬렉션의 인터페이스입니다. 큐의 뒤(rear)에서 요소를 삽입하고 큐의 앞(front)에서 요소를 삭제합니다. 중복 요소도 허용합니다. 주요 구현 클래스는 다음과 같습니다.

  • PriorityQueue: 우선순위에 따라 요소가 정렬돼 처리되는 큐
  • ArrayDeque: Queue 인터페이스를 상속받은 Deque 인터페이스를 구현한 클래스로, 큐와 스택으로 모두 사용 가능
  • LinkedList: Queue 인터페이스를 구현해 FIFO(선입선출) 방식으로 요소를 관리할 수도 있음

6) Deque 인터페이스 (Double-Ended Queue)

Deque(덱)은 Double-Ended Queue의 약자로, 양방향 큐를 정의하는 인터페이스입니다. 큐의 양쪽 끝에서 요소를 추가하고 삭제할 수 있는 자료구조입니다. 스택과 큐의 기능을 둘 다 지원해 LIFO(후입선출)와 FIFO(선입선출) 2가지 방식으로 데이터를 처리할 수 있습니다.

  • Stack: 자바에서 제공하는 전통적인 스택 클래스로, Vector 클래스를 상속받아 구현되며, LIFO 방식을 따름
  • ArrayDeque: 더 현대적인 스택 클래스로, 스택과 큐의 모든 기능을 지원함

10.1.3 래퍼 클래스 (Wrapper Class)

컬렉션 프레임워크를 이해하는 데 필요한 개념 중 하나로 래퍼 클래스가 있습니다.
래퍼 클래스(Wrapper Class)기본형 데이터를 객체로 변환하는 클래스입니다.

기본형과 참조형

자바의 자료형은 기본형(Primitive Type)참조형(Reference Type)으로 나뉩니다.

  • 기본형: 정수형, 실수형, 문자형, 논리형과 같이 실제 값을 저장합니다.
  • 참조형: 객체를 저장하며, 객체의 메모리 주소를 참조합니다.

기본형(Primitive Type)

  • 실제 값을 저장하는 변수
  • 정수, 실수, 문자, 논리값 등을 저장
  • 객체가 아니며, 메모리(Stack)에 직접 저장됨
  • 예: int, double, char, boolean

참조형(Reference Type)

  • 객체를 저장하는 변수
  • 실제 데이터를 메모리(Heap)에 저장하고, 변수에는 객체의 메모리 주소를 저장
  • 예: String, Integer, ArrayList, HashMap 등 모든 클래스와 배열

컬렉션에는 객체(참조형)만 저장할 수 있는 이유

자바의 컬렉션 프레임워크(List, Set, Map 등)는 객체(참조형)만 저장할 수 있습니다.
그 이유는 컬렉션이 Object 타입을 기반으로 설계되었기 때문입니다.

Object는 자바에서 모든 클래스의 최상위 클래스입니다.
즉, 컬렉션이 데이터를 저장할 때 모든 요소를 Object 타입으로 저장합니다.

예시

ArrayList<Object> list = new ArrayList<>();

이처럼 자바의 컬렉션에는 객체만 저장할 수 있기 때문에 기본형 데이터를 컬렉션에 저장하려면 래퍼 클래스를 사용해야 합니다.

기본형과 대응되는 래퍼 클래스

자바의 기본형에는 각각 대응되는 래퍼 클래스가 존재하며, 이는 java.lang 패키지에 포함되어 있습니다.

기본형래퍼 클래스기본형래퍼 클래스
byteByteshortShort
intIntegerlongLong
floatFloatdoubleDouble
charCharacterbooleanBoolean

박싱(Boxing)과 언박싱(Unboxing)

기본형 데이터를 래퍼 클래스로 변환하는 과정을 박싱(Boxing)이라고 하며,
래퍼 클래스 객체를 기본형 데이터로 변환하는 과정을 언박싱(Unboxing)이라고 합니다.

박싱 예제

int num = 10;
Integer obj = Integer.valueOf(num); // int → Integer 변환 (박싱)

언박싱 예제

Integer obj = new Integer(20);
int num = obj.intValue(); // Integer → int 변환 (언박싱)

오토박싱(AutoBoxing)과 오토언박싱(AutoUnboxing)

자바 5 이후부터는 박싱과 언박싱이 자동으로 수행되도록 개선되었습니다.

오토박싱 예제

Integer obj = 10; // 자동으로 int → Integer 변환 (오토박싱)

오토언박싱 예제

int num = obj; // 자동으로 Integer → int 변환 (오토언박싱)

오토박싱과 오토언박싱을 사용하면 개발자가 명시적으로 형변환할 필요 없이 기본형과 객체를 편리하게 사용할 수 있습니다.

10.1.4 제네릭

제네릭(generic)은 타입 안전성을 보장하고 코드 재사용성을 높이기 위해 자바에 도입된 기능입니다. 제네릭은 타입 매개변수를 사용합니다.
타입 매개변수는 인터페이스, 클래스, 메서드를 정의할 때 자료형을 지정하지 않고 나중에 지정할 수 있게 하는 변수입니다. 나중에 사용할 때 해당 객체에 저장할 수 있는 값의 자료형을 넣습니다. 즉, 메서드의 매개변수처럼, 클래스나 메서드의 “타입”을 나중에 결정할 수 있게 해주는 것입니다.
자료형을 마치 메서드의 매개변수처럼 다룬다고 해서 타입 매개변수라고 합니다.

타입 안전성은 프로그래밍 언어에서 데이터의 자료형이 예상하지 못한 방식으로 변환되거나 잘못된 자료형의 데이터가 사용되는 것을 방지하는 성질을 의미합니다.

형식

class 클래스명<타입_매개변수> {} // 클래스
public <타입_매개변수> 반환형 메서드명(타입_매개변수 매개변수); // 메서드

예시: 제네릭을 사용한 코드 (타입 매개변수 적용)

// 타입 매개변수 T 사용 (나중에 실제 타입 지정 가능)
public class Box<T> {
	private T value; // 타입 매개변수 T 사용
    
    public void setValue(T value) {
    	this.value = value;
    }
    
    public T getValue() {
    	return value;
    }
}
  • T타입 매개변수이며, 나중에 실제 타입(String, Integer 등)으로 지정 가능
  • 타입 안전성 보장 (잘못된 타입 저장 불가, 타입 캐스팅 필요 없음)

예시: 제네릭 클래스 사용

public class Main {
	public static void main(String[] args) {
    	// String 타입을 저장하는 Box 객체 생성
        Box<String> stringBox = new Box<>();
        stringBox.setValue("Hello");
        String str = stringBox.getValue(); // 형변환 불필요
        System.out.println(str);
        
        // Integer 타입을 저장하는 Box 객체 생성
        Box<Integer> intBox = new Box<>();
        intBox.setValue(100);
        Integer num = intBox.getValue();
        System.out.println(num);
    }
}
  • Box<String> → T가 String으로 지정됨
  • Box<Integer> → T가 Integer로 지정됨
  • 타입 캐스팅이 필요 없음 (안전함)

예시: 제네릭 메서드에서 타입 매개변수 사용

제너릭을 클래스뿐만 아니라 메서드에도 사용할 수 있습니다.

public class GenericMetho {
	public static <T> void print(T item) {
    	System.out.println(item);
    }
    
    public static void main(String[] args) {
    	print("Hello"); // T가 String으로 결정됨
        print(100);		// T가 Integer로 결정됨
        print(3.14);	// T가 Double로 결정됨
    }
}
  • <T>메서드에서 사용할 타입 매개변수를 정의
  • 호출할 때 전달된 값의 타입에 따라 T가 자동으로 결정됨

타입 매개변수는 주로 알파벳 대문자 한 글자로 표현합니다. 암묵적인 규칙일 뿐이고 다른 문자를 사용해도 됩니다. 일반적으로 많이 사용하는 타입 매개변수는 다음과 같습니다.

  • <T>(Type): 클래스나 메서드에서 가장 많이 사용하는 형태의 타입 매개변수입니다. T는 Integer, String, Double 등 다양한 참조형으로 대체할 수 있습니다.
  • <E>(Element): 주로 ListSet의 구현 클래스에서 요소를 나타낼 대 사용합니다. E는 각 요소의 자료형을 의미합니다.
  • <K, V>(Key, Value): Map처럼 키-값 쌍을 다루는 자료구조에서 사용합니다. K는 키의 자료형을, V는 값의 자료형을 나타냅니다.
  • <N>(Number): 주로 숫자형을 다루는 클래스나 메서드에서 사용합니다.

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

10.2.1 List 인터페이스

10.2.2 Set 인터페이스

10.2.3 Map 인터페이스

profile
donggyun_ee

0개의 댓글