본 글은 책 자바의 정석을 ref 하여 요약한 것입니다.
✔ 스트림
자바 8부터 추가된 함수적 스타일 처리
중간처리는 지연되고, 최종 처리가 시작되면 처리를 시작한다.
✔ 스트림의 종류
Stream, IntStream, LongStream, DoubleStream
✔ 스트림 만들기
List<Integer> list = Arrays.asList(1,2,5,3);
Stream<Integer> slist= list.stream();
long[] arr = {1,2,10,5,3,4,3};
LongStream sarr = Arrays.stream(arr);
컬렉션 프레임워크는 Stream<T> 로 변환된다.
mapToXXX()로 변환하면 IntStream, LongStream, DoubleStream로 변경할 수 있다.
기본형 배열은 type에 맞게 IntStream, LongStream, DoubleStream 로 변환된다.
객체 배열일 경우 Stream<T> 로 변환된다.
객체는 Stream<T>
기본형 배열은 IntStream, LongStream, DoubleStream
✔ 중간 처리 함수
매핑, 필터링, 정렬
skip(n)
개수만큼 건너뛴다.
limit(n)
개수만큼 제한한다.
peek(Consumer)
forEach와 비슷한 역할을 하는 중간 연산이라고 보면 된다.
보통 단순히 중간 조회를 위해 사용됨
distinct()
중복을 제거한다. equals() 값이 같으면 제거, IntStream, LongStream, DoubleStream 일 경우 값이 같으면 제거
filter(Predicate)
true인 값만 남기고 제거한다.
map(Function)
요소를 대체하는 새로운 요소로 구성된 스트림을 만든다. (보통 type변환, 일괄 연산 등)
map() -> (객체 -> 객체), (기본형 -> 기본형), 값 변환
mapToInt -> IntStream으로 변환
mapToLong -> LongStream으로 변환
mapToDouble -> LongStream으로 변환
mapToObj -> 객체로 변환
type 변환과 값 변경도 가능
List<Integer> list = Arrays.asList(1,2,5,3);
Stream<Integer> slist= list.stream();
IntStream is = slist.mapToInt(e->e);
long[] arr = {1,2,10,5,3,4,3};
LongStream sarr = Arrays.stream(arr);
Stream<Integer> bs = sarr.mapToObj(e -> (int) e);
flatMap()
스트림의 요소가 배열일때 flatten Stream을 만들 때 사용한다.
boxed()
IntStream, LongStream, DoubleStream ----> Stream<T>
sorted(Comparator)
정렬을 제공한다.
Comparable이 제공된 객체를 사용하거나, Comparator를 제공해주면 된다.
* IntStream, LongStream, DoubleStream 일 경우 인수를 제공하지 않으면 오름차순으로 정렬, 내림차순을 원할 경우 Comparator.reverseOrder()
* thenComparing() - 정렬 추가가 가능
* reversed() - 내림차순 가능
List<Student> students = Arrays.asList(
new Student("Lee", 1),
new Student("Lee", 2),
new Student("Park",1),
new Student("Park",2),
new Student("Kim",2)
);
List<Student> sortedList= students.stream().sorted(
Comparator.comparing(Student::getName)
.thenComparing(Student::getNumber)
.reversed()
).collect(Collectors.toList());
System.out.println(sortedList);
// [Student{name='Park', number=2}, Student{name='Park', number=1},
// Student{name='Lee', number=2}, Student{name='Lee', number=1}, Student{name='Kim', number=2}]
✔ 최종 처리 함수
반복, 카운팅, 평균, 총합
최종 처리 함수의 반환 타입은 기본형이거나 OptionalXXX
forEach(Consumer)
요소를 하나하나씩 처리한다.
sum() - IntStream, LongStream, DoubleStream
반환 타입
타입에 맞는 기본형
count() - IntStream, LongStream, DoubleStream
반환 타입
long
max(), min() - IntStream, LongStream, DoubleStream
Stream<T> 일 경우 인수로 Comparator 필요
IntStream, LongStream, DoubleStream 일 경우 필요하지 않다.
반환 타입
Stream<T>일 경우 Optional<T>
IntStream, LongStream, DoubleStream 일 경우 OptionalXXX
average() - IntStream, LongStream, DoubleStream
반환 타입
OptionalDouble
findFirst()
반환 타입
Stream<T>일 경우 Optional<T>
IntStream, LongStream, DoubleStream 일 경우 OptionalXXX
reduce(identify, BinaryOperator)
identify는 요소가 없을 때 반환하는 값(Default)
BinaryOperator에 요소 하나하나씩 누적해가며 계산한다.
반환 타입
identify를 지정하면 기본형으로 반환
지정하지 않으면 OptionalXXX로 반환
allMatch(Predicate)
모든 요소가 일치하면 true 반환
anyMatch(Predicate)
하나의 요소라도 true라면 true 반환
noneMatch(Predicate)
모든 요소가 false라면 true 반환
✔ collect(Collector)
collect 함수는 내부에 수집기를 정의해줘야 한다.
보통 Collectors(수집기 구현체)에 구현된 메서드들을 활용한다.
Student[] students = {new Student("Lee",23), new Student("Park",26), new Student("Kim",26)};
List<Integer> ageList = Arrays.stream(students)
.map(e-> e.age)
.collect(Collectors.toList());
System.out.println("ageList " + ageList);
Set<Integer> ageSet = Arrays.stream(students)
.map(e-> e.age)
.collect(Collectors.toSet());
System.out.println("ageSet " + ageSet);
TreeSet<Integer> ageTreeSet = Arrays.stream(students)
.map(e -> e.age)
.collect(Collectors.toCollection(()-> new TreeSet<Integer>())); // TreeSet::new
System.out.println("ageTreeSet " + ageTreeSet.higher(23));
collect() 사용자 직접 정의
Collector(수집기) 인터페이스를 구현하기 위해선 대략 3가지의 요소가 필요하다.
supplier
- 수집된 데이터를 담을 구현체 생성 (싱글 스레드는 하나, 멀티 스레드는 여러개가 생성)
accumalator
- 생성된 객체에 원하는 요소 수집
combiner
- 병렬 처리된 각 컨테이너 객체들을 결합 지정
List<Student> students = Arrays.asList(
new Student("Lee", 1),
new Student("Park",1),
new Student("Kim",2),
new Student("Cha",2)
);
List<Student> ls = students.stream().
filter((s)-> s.getNumber() == 1).
collect(ArrayList::new, List::add, List::addAll);
System.out.println(ls);
// [Student{name='Lee', number=1}, Student{name='Park', number=1}]
collect() 그룹핑
Collectors.groupingBy()
- 내부에서 key, Collector(수집기)를 지정한다.
Collectors.mapping(Function, Collector)
- 매핑한 후 Collector(수집기)를 사용한다.
List<Student> students = Arrays.asList(
new Student("Lee", 1),
new Student("Park",1),
new Student("Kim",2),
new Student("Cha",2)
);
Map<Integer, List<Student>> m1 = students.stream()
.collect(Collectors.groupingBy(Student::getNumber)); // key
System.out.println(m1);
// {1=[Student{name='Lee', number=1}, Student{name='Park', number=1}], 2=[Student{name='Kim', number=2}, Student{name='Cha', number=2}]}
Map<Integer,List<String>> m2 = students.stream()
.collect(Collectors.groupingBy(
Student::getNumber, // key
Collectors.mapping(Student::getName, Collectors.toList()))); // value
System.out.println(m2);
// {1=[Lee, Park], 2=[Kim, Cha]}
Map<Integer,List<String>> m3 = students.stream()
.collect(Collectors.groupingBy(
Student::getNumber, // key
HashMap::new, // 구현체 지정 가능
Collectors.mapping(Student::getName, Collectors.toList()))); // value
System.out.println(m3);
// {1=[Lee, Park], 2=[Kim, Cha]}
partioningBy(Predicate, Collector)
true인 것만 적용하여 분리
반환 타입은 <boolean>
Collectors 수집기 함수
averagingDouble()
counting()
maxBy(Comparator)
minBy(Comparator)
summingInt, Long, Double()
reducing(identity, BinaryOperator)
joining(구분자) - 문자열 결합
collect 개략도
collect( 수집기 )
collect( Collectors.groupingBy ( 키, 수집기 ) )
collect( Collectors.groupingBy ( 키, Collectors.mapping ( 매핑, 수집기 ) )
'프로그래밍 > 자바' 카테고리의 다른 글
[JAVA] 메서드 체이닝 만들기 (빌더 패턴) (0) | 2022.08.26 |
---|---|
[JAVA] 13장. 쓰레드 (0) | 2022.07.31 |
[JAVA] 12장. 제네릭스, 열거형, 어노테이션 (0) | 2022.07.31 |
[Java] equals()와 hashCode() 사용, HashSet에서의 활용 (0) | 2022.07.30 |
11장 컬렉션 프레임 워크 (0) | 2022.07.28 |