Wrapper 클래스
- 8가지 기본 데이터 타입 (primitive data type) 을 객체로 표현하기 위해 제공되는 클래스
- 객체로서 다양한 메서드와 속성 사용
- 장점
- 컬렉션 저장
- 자바의 컬렉션 (ex. ArrayList) 은 기본 데이터 타입을 직접 저장 ❌
- 기본 타입을 저장하고 싶을 때 wrapper 클래스 사용
- Null 값 허용
- 기본 데이터 타입은 null 값을 가질 수 없음
- 어떤 값이 없거나 알 수 없는 경우를 표현하고 싶을 때, wrapper 클래스는 null 값을 가질 수 있음
- 메서드와 유틸리티
- wrapper 클래스는 문자열 변환, 값 비교와 같은 유용한 메서드 제공
- 메서드 매개변수
- 메서드에 객체를 매개변수로 전달하거나 반환해야 할 때, wrapper 클래스가 유용
- 종류
- byte - Byte
- short - Short
- int - Integer
- long - Long
- float - Float
- double - Double
- char - Character
- boolean - Boolean
auto-boxing & auto-unboxing
- auto-boxing : 기본 데이터 타입을 wrapper 클래스 객체로 자동 변환
- auto-unboxing : wrapper 클래스 객체를 기본 데이터 타입으로 자동 변환
ArrayList<Integer> numbers = new ArrayList<>();
numbers.add(1);
numbers.add(2);
int sum = numbers.get(0) + numbers.get(1);
System.out.println("합계 : " + sum);
Generic
- 자바에서 타입 안정성 (type safety) 을 높이기 위해 도입된 프로그래밍
- 장점
- 타입 안정성 : 잘못된 타입의 객체가 저장되는 것을 컴파일 시간에 방지
- 형 변환 필요성 감소 : 제네릭을 사용하면, 명시적인 형 변환 필요 ❌
- 코드 재사용성 : 일반 클래스나 메서드로 다양한 타입에 대해 동작하는 코드를 작성할 수 있음
pulbic class MyCustomList {
Arraylist<String> list = new ArrayList<>();
public void addElement(String element) {
list.add(element);
}
public void removeElement(String element) {
list.remove(element);
}
}
pulbic class MyCustomList<T> {
Arraylist<T> list = new ArrayList<>();
public void addElement(T element) {
list.add(element);
}
public void removeElement(T element) {
list.remove(element);
}
}
class Utility {
public static void printPair(String first, String second) {
System.out.println("(" + first + ", " + second + ")");
}
public static void main(String[] args) {
printPair("apple", "banana");
}
}
class Utility {
public static <T> void printPair(T first, T second) {
System.out.println("(" + first + ", " + second + ")");
}
public static void main(String[] args) {
printPair("apple", "banana");
printPair(1, 2);
printPair(1.5, 2.5);
}
}
제네릭 제한
- extends 키워드를 제네릭에서 사용하면, 해당 타입 파라미터에 대한 상한 지정
→ 타입 파라미터가 특정 클래스의 자식 클래스, 또는 특정 인터페이스의 구현 클래스만 가능하도록 제한할 수 있음
- ex)
와일드카드
- 알 수 없는 타입을 의미함
- 제네릭 코드에서 더 큰 유연성을 얻기 위해 사용되며, 특히 제네릭 메서드나 제네릭 클래스에서 다양한 제네릭 타입을 처리할 때 유용하게 사용됨
- ? (Unbounded Wildcard) : 어떠한 타입이든 모두 가능
- ? extends T (Upper Bounded Wildcard) : T 타입 또는 T의 서브 타입
- ? super T (Lower Bounded Wildcard) : T 타입 또는 T의 슈퍼 타입
Collection
- 데이터 구조와 알고리즘을 제공하는 프레임워크
- 객체의 그룹을 효율적으로 관리하기 위한 다양한 클래스와 인터페이스 제공
- Collection 프레임워크의 주요 인터페이스
- Collection : 가장 기본적인 인터페이스로, 모든 collection 클래스가 이를 구현
- List : 데이터 순서 유지 ⭕ 중복 ⭕
- Set : 데이터 순서 유지 ❌ 중복 ❌
- Map : 키-값 쌍으로 데이터 저장. 키는 중복 ❌
List
- 순서가 있는 컬렉션
- 요소의 순서 유지 ⭕ 중복된 요소 ⭕
- 주요 메서드
- add(E element) : 요소를 리스트의 끝에 추가
- add(int index, E element) : 지정된 위치에 요소 삽입
- get(int index) : 지정된 위치의 요소 반환
- remove(int index) : 지정된 위치의 요소를 삭제하고 반환
- set(int index, E element) : 지정된 위치의 요소를 지정된 요소로 교체
- indexOf(Object o) : 지정된 요소의 인덱스 반환 (존재하지 않는 경우, -1 반환)
- size( ) : 리스트의 크기 반환
- ArrayList
- List 인터페이스의 동적 배열 구현
- 초기 크기가 있지만, 요소가 추가됨에 따라 자동으로 크기가 확장됨
- 배열 기반이므로 인덱스를 사용한 요소 접근이 빠름
- 중간에 요소를 삽입하거나 삭제하는 연산은 느림
- LinkedList
- List와 Deque 인터페이스의 양방향 연결 리스트 구현
- 연결 리스트 기반이므로 중간에 요소를 삽입하거나 삭제하는 연산이 빠름
- 인덱스를 사용한 요소 접근은 느림
Set
- 데이터 순서 유지 ❌ 중복 ❌
- 주요 메서드
- add(E element) : 요소를 set에 추가함. 요소가 이미 존재할 경우에는 추가 ❌
- remove(Object o) : 지정된 요소를 set에서 제거
- contains(Object o) : set가 지정된 요소를 포함하고 있는지 확인
- size( ) : set의 크기 (요소의 수) 를 반환
- isEmpty( ) : set가 비어있는지 확인
- clear( ) : set의 모든 요소 제거
- HashSet
- Set의 대표적인 클래스로, 해시 테이블을 사용하여 요소 저장
- 데이터 순서 유지 ❌ 중복 ❌
- LinkedHashSet
- HashSet을 확장하여 요소의 삽입 순서를 기억
→ 요소의 삽입 순서대로 반복
- TreeSet
- 자동으로 정렬된 순서로 요소를 저장
- 사용자 정의 정렬 가능
Map
- 키와 값을 쌍으로 저장하는 데이터 구조
- 각 키는 고유해야 함
- 주요 메서드
- put(K key, V value) : 지정된 키와 값을 map에 저장
- get(Object key) : 지정된 키에 연관된 값을 반환
- remove(Object key) : 지정된 키와 그에 연관된 값을 map에서 제거
- containsKey(Object key) : map이 지정된 키를 포함하고 있는지 확인
- containsValue(Object value) : map이 지정된 값을 포함하고 있는지 확인
- size( ) : map에 저장된 키-값 쌍의 수를 반환
- clear( ) : map의 모든 키-값 쌍을 제거
- HashMap
- 해시 테이블을 사용하여 키-값 쌍을 저장
- 데이터 순서 유지 ❌
- LinkedHashMap
- HashMap을 확장하여 키-값 쌍의 삽입 순서나 접근 순서 기억
- 순서가 중요한 경우에 유용
- TreeMap