STUDY/Java
[Java] 컬렉션 (Collection)
ofijwe
2024. 10. 30. 17:14
반응형
📒 List 계열
1️⃣ 자료구조
- 데이터 값의 모임, 또 데이터 간의 관계, 그리고 데이터에 적용할 수 있는 함수나 명령을 의미
2️⃣ 배열
- 가장 기본적인 자료 구조
- homeogeneous collection : 동일한 데이터 타입만 관리 가능
- Polymorphism
- Object를 이용하면 모든 객체 참조 가능 → Collection Framework
- 담을 땐 편리, 빼낼 땐 Object로만
- 런타임에 실제 객체의 타입 확인 후 사용해야 하는 번거로움
- Generic을 이용한 타입 한정
- 컴파일 타임에 저장하려는 타입 제한 → 형변환의 번거로움 제거
3️⃣ Collection Framework
- java.util 패키지
- 다수의 데이터를 쉽게 처리하는 방법 제공 → DB처럼 CRUD 기능 중요
- Collection framework 핵심 interface
- List : 입력 순서가 있는 데이터 집합
- Set : 입력 순서를 유지하지 않는 데이터의 집합
- Map : key와 value의 쌍으로 데이터를 관리하는 집합
- Collection interface (CRUD)
4️⃣ Collection Framework - List
- 특징
- 입력 순서가 있는 데이터의 집합
- 입력 순서가 있으므로 데이터의 중복 허락
- 배열과 ArrayList
- 장점
- 가장 기본적인 형태의 자료 구조로 간단하며 사용이 쉬움
- 접근 속도가 빠름
- 단점
- 크기를 변경할 수 X, 추가 데이터를 위해 새로운 배열을 만들고 복사해야 함
- 비 순차적 데이터의 추가, 삭제에 많은 시간이 걸림
- 장점
- LinkedList
- 각 요소를 Node로 정의하고 Node는 다음 요소의 참조 값과 데이터로 구성됨
- 각 요소가 다음 요소의 링크 정보를 가지며 연속적으로 구성될 필요 X
- 결론
- 특정 클래스가 좋고 나쁨이 나닌 용도에 적합하게 사용해야 함
- 소량의 데이터를 가지고 사용할 경우 큰 차이 X
- 정적인 데이터 활용, 단순한 데이터 조회 → ArrayList
- 동적인 데이터 추가, 삭제가 많은 작업 → LinkedList
- 자료 삭제 시 주의사항
- index를 이용한 for문
- 요소가 삭제되면 size가 줄어들기 때문에 index 차감 필요
- 거꾸로 접근하면 자연스럽게 해결
- forEach 문장은 Collection 크기가 불변해야함.
- index를 이용한 for문
📒 Set 계열
1️⃣ Set interface
- 입력 순서 관리 X, 주머니에 데이터를 넣는 형태
- 데이터를 구별할 순서 X, 중복 허용 X
📒 Map 계열
1️⃣ Map interface
- Key와 Value를 하나의 Entry로 묶어서 데이터 관리
- Key : Object 형태로 데이터 중복을 허락 X
- Value : Object 형태로 데이터 중복 허락 O
📒 정렬
1️⃣ 정렬
- 요소를 특정 기준에 대한 내림차순 또는 오름차순으로 배치하는 것
- 크기를 비교할 수 있는 요소를 가지는 Colection들만 정렬 가능
- List 계열
- Set에서는 SortedSet의 자식 객체
- Map에서는 SortedMap의 자식 객체(key 기준)
- Collections의 sort()를 이용한 정렬
- sort(List
<T>
list)
- sort(List
2️⃣ Comparator의 활용
- 객체가 Comparable을 구현하고 있지 않거나 사용자 정의 알고리즘으로 정렬하려는 경우
- sort(List
<T>
list, Comparator<? Super T> c) public interface Comparator<T> { int compare(T o1, T o2); } public class StringLengthComparator implements Comparator<String> { @Override public int compare(String o1, String o2) { int len1 = o1.length(); int len2 = o2.length(); return Integer.compare(len1, len2); } } public void StringLengthSort() { Collections.sort(names, new StringLengthComparator()); System.out.println(names); }
- 1회성 객체 사용 시 anonymous inner class 사용
- 클래스 정의, 객체 생성 한 번에 처리
Collections.sort(names, new StringLengthComparator()); Collections.sort(names, new Comparator<String>() { @Override public int compare(String o1, String o2) { return Integer.compare(o1.length(), o2.length()); } });
- 람다 표현식 이용
Collections.sort(names, (o1, o2) -> { return Integer.compare(o1.length(), o2.length()); });
📒 Lambda 표현식
1️⃣ Lambda 식
- 함수적 프로그래밍의 형태로 재사용 가능한 코드 블록
- 기존의 anonymous inner class를 이용한 처리 방식을 간결하게 처리
2️⃣ Lambda 표현식
- 타겟 타입 또는 함수형 인터페이스
- Lambda 식이 할당되는 인터페이스를 Lambda 식의 타겟 타입이라 함.
- 타겟 타입은 abstract 메서드가 반드시 하나만 존재해야 함(default, static 등 무관)
- @FunctionalInterface
- 컴파일러가 하나의 abstract method만 있음을 체크
- 그렇지 않을 경우 오류 발생 → 안정적인 programming을 위한 option
- abstract method가 2개 이상 존재하는 경우는 여전히 익명의 inner class 사용
- 기본 Lambda 식 : @FunctionalInterface에 대한 구현체 작성법
- (type variable_name[,…]) → {실행문;};
3️⃣ Lambda 실행 블록에서의 변수 참조
- Lambda 식 내부에서의 this는 외부 클래스의 instacne
- 외부 클래스의 member 변수 : 접근제한자의 제약 없이 사용 가능
- 외부 메서드의 local 변수 : final 키워드가 추가된 것으로 동작 → read only
4️⃣ 함수형 프로그래밍
- java.util.function package
- 일반적으로 객체지향의 java 프로그래밍은 메서드의 구조와 이름이 중요
- 일반적인 함수형 프로그래밍 언어에서 함수의 타입은 구조적이며 이름이 불필요
5️⃣ 표준 API
- 기본 제공 API 종류
- 자주 사용되는 함수적 표준 interface를 java.util.function package에 정의
- 주로 메서드 또는 생성자의 parameter로 Lambda식을 제공하기 위함
- Consumer 계열
- parameter는 있으며 return이 없는 형태
- parameter 타입에 따라 다양한 consumer 존재
- Supplier 계열
- parameter는 없으며 return이 있는 형태
- retrun 타입에 따라 다양한 supplier 존재
- Function 계열
- parameter와 return 값이 있는 형태
- parameter와 return type에 따라 다양한 인터페이스 존재
- 주로 파라미터를 이용해 연산을 수행한 후 원하는 타입으로 반환하는 역할
- Operator 계열
- function 계열과 유사: parameter와 return 값을 가짐
- Predicate 계열
- parameter를 받고 boolean 타입을 리턴
6️⃣ 메서드 참조와 생성자 참조
- 람다 실행문 내부에서 다른 함수 하나만을 실행하는 겨우 :: 연산자를 이용해 기존 메서드 참조
- <소유자>::<파라미터를 사용하는 소유자의 메서드>
- 파라미터의 인스턴스 메서드 참조
- 객체의 클래스 :: 인스턴스 메서드
- 첫 번재 파라미터는 메서드의 소유자
- 나머지 파라미터는 메서드의 파라미터 순서대로 전달
- 정적 메서드 참조
- 클래스::정적 메서드
- 모든 파라미터가 메서드의 파라미터로 순서대로 전달됨
- 특정 객체의 instance의 메서드 참조
- 객체 :: 인스턴스 메서드 형태
- 객체의 메서드가 호출되며 파라미터는 메서드에 그대로 전달됨
- 생성자 참조
- 클래스명 :: new의 형식으로 생성자 참조
- 파라미터의 개수, 타입에 의해 호출되는 생성자 결정
📒 Stream API
1️⃣ Stream
- JDK 8에 추가된 java.util.stream package
- 배열 및 Collection의 요소를 하나씩 참조해서 처리하는 목적
- 람다와 내부 반복자를 이용해 컬렉션을 다루는 코드 간결화
- Stream API 역할 및 특징
- 컬렉션, 배열 등 데이터 소스에 대한 공통된 접근 방식 제공
- 손쉬운 병렬 처리
2️⃣ Stream 자료 처리
- 맵/리듀스 모델 지원
- 맵: 데이터를 작은 단위로 나누어 처리
- 리듀스: 결과를 모아서 최종 결과를 생성
- 중간 처리들과 최종 처리를 조합해 사용
- 중간 처리: 매핑, 필터링, 정렬 등 가공 처리
- 최종 처리: 반복, 카운팅, 평균, 총합 등 집계 처리
- 각각의 중간 처리는 새로운 스트림을 리턴하여 builder 패턴 적용
- 기존 스트림의 내용을 수정하지 않음
- 최종 처리는 최종적으로 원하는 값을 반환 → 한번 최종 처리 끝난 스트림 재사용 X
- Stream의 종류와 획득
- java.util.stream package에 정의
- 종류
- Stream - 객체 요소에 대한 처리
- IntStream, LongStream, DoubleStream - 각각 int, long, double 데이터 처리
- 획득
- Collection, 배열, File, Random 및 Stream 클래스의 static method로 생성
3️⃣ 중간 처리
- 필터링
- 자르기
- 정렬
- 매핑(변환) - 스트림의 요소를 다른 요소로 대체하는 작업
- 조회(주석)
4️⃣ 최종 처리
- 반복 - forEach()
- 매칭
- 통계 - count(), sum() …
- 집계(aggregate)
- 사용자 정의 집계 처리 - reduce()
- 조사 - findFirst(), findAny()
- 결과 모으기 - collect()
- 결과 모으기 - 분할(partioningBy())과 그룹핑(groupingBy())
반응형