List<String> list = ................;
for(int i=0; i<list.size(); i++){
String item = list.get(i);
// item 처리
}
Set<String> set = ...............;
Iterator<String> iterator = set.iterator();
while(iter.hasNext()) {
String item = iterator.next()
// 요소 처리
}
// STREAM 처리
Stream<String> stream = list.stream();
stream.forEach(item -> // item 처리);
기존 JAVA에서 컬렉션 데이터를 처리할떄 특정 조건에 따라 필터링을 하려면 복잡한 과정을 거쳐야 한다.
반면에 SQL 문법의 경우 사용자가 원하는 조건의 데이터 목록을 검색할 때 명시적이고 간단한 방법을 이용하는데 JAVA 8에서 새로 추가된
기능인 스트림은 JAVA의 컬렉션 데이터에 대해 SQL 질의문처럼 데이터를 처리 할 수 있는 기능을 가진다.
기존 루프문 처리의 문제점
기존 JAVA에서 컬렉션 데이터를 처리할 떄는 for, foreach 루프문을 사용하면서 컬렉션 내의 요소들을 하나씩 다룬다.
간단한 처리나 컬렉션의 크기가 작으면 큰 문제가 아니지만 복잡한 처리가 필요하거나 컬렉션의 크기가 커지면 루프문의 사용은 성능저하를
이르키게 된다.
스트림
스트림은 컬렉션 데이터를 선언형으로 쉽게 처리할 수 있다. 복잡한 루프문을 사용하지 않아도 되며 루프문을 중첩해서 사용해야 되는 최악의 경우도 없어지게 된다. 또한 스트림은 병렬처리(Multi thread)를 별도의 멀티스레드 구현없이도 쉽게 구현이 가능하다.
Iterator : 외부 반복자 : 개발자 코드에서 컬렉션의 요소를 하나 가져와서 처리하고 다시 컬렉션의 요소를 하나 가져와서 처리
stream : 내부 반복자 : 개발자 코드에서 컬렉션의 요소를 하나씩 처리, 컬렉션의 요소를 하나씩 처리
Stream은 Iterator 와 비슷한 반복자이지만 다음과 같은 차이점을 가지고있다.
1) 내부 반복자이므로 처리 속도가 빠르고 병렬 처리에 효율적이다.
2) 람다식으로 다양한 요소 처리를 정의 할 수 있다
3) 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성 할 수 있다.
Comparable과 Comparator는 둘 다 인터페이스
정렬에 사용
객체를 비교할 수 있다.
Comparable : compareTo 메서드 구현
자기 자신과 매개변수 객체를 비교
compareTo( T o)
Comparator : compare 메서드 구현
두 매개변수 객체를 비교
compare( T o1, T o2)
Optional 클래스
java.util.Optional<T>
Optional은 선택형 값을 캡슐화하는 클래스이다.
값이 있으면 Optional 클래스는 값을 감싼다.
값이 없으면 Optional.empty 메서드로 Optional을 반환한다.
기본 타입 래퍼클래스 (Wrapper class)
byte -> Byte
short -> Short
int -> Integer
long -> Long
float -> Float
double -> Double
char -> Char
boolean -> Boolean
기본타입의 데이터를 객체로 취급해야 하는 경우
메서드의 인수로 객체 타입만이 요구되며, 기본 타입의 데이터를 그대로 사용할 수 가 없다.
이때 기본타입의 데이터를 객체로 변환한 후 작업을 수행해야 한다.
값이 없을 경우 디폴트 값을 설정하거나 집계값을 처리하는 Consumer를 등록 할 수 있다.
isPresent() 메서드가 true를 리턴 할 때만 집계값을 얻는다.
orElse() 메서드로 집계값이 없을 경우를 대비해서 디폴트 값을 정해 놓는다.
ifPresent() 메서드로 집계값이 있을 경우에만 동작하는 Consumer 람다식을 제공한다,
OptionalDouble optional = stream.average();
if(optional.isPresent()) {
System.out.println("평균 : " + optional.getAsDouble());
} else {
System.out.println("평균 : 0.0");
}
orElse() 메서드로 집계값이 없을 경우를 대비해서 디폴트 값을 정해 놓는다.
double avg = stream.
.average()
.orElse(0,0);
System.out.println("평균 : " + avg);
ifPresent() 메서드로 집계값이 있을 경우에만 동작하는 Consumer 람다식을 제공한다.
stream
.average()
.ifPresent(a -> System.out.println("평균: " + a);
reduce()
int sum = stream
.reduce((a,b) -> a+b)
.getAsInt();
값이 있을때 정상 동작
값이 없을때 예외 발생 (NoSuchElementException) 예외발생
int sum = stream
.reduce(0, (a, b) -> a+b)
.getAsInt();
매개 값이 있을 경우, a와 b를 더한 값이 리턴
매개 값이 없을 경우 0 -> 리턴 0
스트림이란?
스트림
- Java 8부터 컬렉션 및 배열의 요소를 반복 처리하기 위해 스트림 사용
- 요소들이 하나씩 흘러가면서 처리된다는 의미
- List 컬렉션의 stream() 메소드로 Stream 객체를 얻고, forEach() 메소드로 요소를 어떻게 처리할지를 람다식으로 제공
- 스트림과 Iterator 차이점
- 1) 내부 반복자이므로 처리 속도가 빠르고 병렬 처리에 효율적
- 2) 람다식으로 다양한 요소 처리를 정의
- 3) 중간 처리와 최종 처리를 수행하도록 파이프 라인을 형성
내부 반복자
내부반복자
- 요소 처리 방법을 컬렉션 내부로 주입시켜서 요소를 반복 처리
- 개발자 코드에서 제공한 데이터 처리 코드(람다식)를 가지고 컬렉션 내부에서 요소를 반복 처리
- 내부 반복자는 멀티 코어 CPU를 최대한 활용하기 위해 요소들을 분배시켜 병렬 작업 가능
중간 처리와 최종 처리
스트림 파이프라인
- 컬렉션의 오리지널 스트림 뒤에 필터링 중간 스트림이 연결될 수 있고, 그 뒤에 매핑 중간 스트림이 연결될 수 있음
- 오리지널 스트림과 집계 처리 사이의 중간 스트림들은 최종 처리를 위해 요소를 걸러내거나(필터링), 요소를 변환시키거나(매핑), 정렬하는 작업을 수행
- 최종 처리는 중간 처리에서 정제된 요소들을 반복하거나, 집계(카운팅, 총합, 평균) 작업을 수행
스트림 인터페이스
- java.util.stream 패키지에는 BaseStream 인터페이스를 부모로 한 자식 인터페이스들은 상속 관계
- BaseStream에는 모든 스트림에서 사용할 수 있는 공통 메소드들이 정의
컬렉션으로부터 스트림 얻기
- java.util.Collection 인터페이스는 스트림과 parallelStream() 메소드를 가지고 있어 자식 인터페이스인 List와 Set 인터페이스를 구현한 모든 컬렉션에서 객체 스트림을 얻을 수 있음
배열로부터 스트림 얻기
- java.util.Arrays 클래스로 다양한 종류의 배열로부터 스트림을 얻을 수 있음
숫자 범위로부터 스트림 얻기
- IntStream 또는 LongStream의 정적 메소드인 range()와 rangeClosed() 메소드로 특정 범위의 정수 스트림을 얻을 수 있음
파일로부터 스트림 얻기
- java.nio.file.Files의 lines() 메소드로 텍스트 파일의 행 단위 스트림을 얻을 수 있음
요소 걸러내기(필터링)
필터링
- 필터링은 요소를 걸러내는 중간 처리 기능
- distinct() 메소드: 요소의 중복을 제거
- filter() 메소드: 매개값으로 주어진 Predicate가 true를 리턴하는 요소만 필터링
- Predicate: 함수형 인터페이스
- 모든 Predicate는 매개값을 조사한 후 boolean을 리턴하는 test() 메소드를 가지고 있다.
요소 변환(매핑)
매핑
- 스트림의 요소를 다른 요소로 변환하는 중간 처리 기능
- 매핑 메소드: mapXxx(), asDoubleStream(), asLongStream(), boxed(), flatMapXxx() 등
요소를 다른 요소로 변환
- mapXxx() 메소드: 요소를 다른 요소로 변환한 새로운 스트림을 리턴
- 매개타입인 Function은 함수형 인터페이스
- 모든 Function은 매개값을 리턴값으로 매핑(변환)하는 applyXxx() 메소드를 가짐
- 기본 타입 간의 변환이거나 기본 타입 요소를 래퍼(Wrapper) 객체 요소로 변환하려면 간편화 메소드를 사용할 수 있음
요소를 복수 개의 요소로 변환
- flatMapXxx() 메소드: 하나의 요소를 복수 개의 요소들로 변환한 새로운 스트림을 리턴
요소 정렬
정렬
- 요소를 오름차순 또는 내림차순으로 정렬하는 중간 처리 기능
Comparable 구현 객체의 정렬
- 스트림의 요소가 객체일 경우 객체가 Comparable을 구현하고 있어야만 sorted() 메소드를 사용하여 정렬 가능. 그렇지 않다면 ClassCastException 발생
Comparator를 이용한 정렬
- 요소 객체가 Comparable을 구현하고 있지 않다면, 비교자를 제공하면 요소를 정렬시킬 수 있음
- 괄호 안에는 o1이 o2보다 작으면 음수, 같으면 0, 크면 양수를 리턴하도록 작성
- o1과 o2가 정수일 경우에는 Integer.compare(o1, o2)를, 실수일 경우에는 Double.compare(o1, o2)를 호출해서 리턴값을 리턴 가능
요소를 하나씩 처리(루핑)
루핑
- 스트림에서 요소를 하나씩 반복해서 가져와 처리하는 것
- 매개타입인 Consumer는 함수형 인터페이스. 모든 Consumer는 매개값을 처리(소비)하는
accept() 메소드를 가지고 있음
요소 조건 만족 여부(매칭)
매칭
- 요소들이 특정 조건에 만족하는지 여부를 조사하는 최종 처리 기능
- allMatch(), anyMatch(), noneMatch() 메소드는 매개값으로 주어진 Predicate가 리턴하는 값에 따라 true 또는 false를 리턴

요소 기본 집계
집계
- 최종 처리 기능으로 요소들을 처리해서 카운팅, 합계, 평균값, 최대값, 최소값 등 하나의 값으로 산출하는 것
스트림이 제공하는 기본 집계
- 스트림은 카운팅, 최대, 최소, 평균, 합계 등을 처리하는 다음과 같은 최종 처리 메소드를 제공
Optional 클래스
- Optional, OptionalDouble, OptionalInt, OptionalLong 클래스는 단순히 집계값만 저장하는 것이 아니라, 집계값이 없으면 디폴트 값을 설정하거나 집계값을 처리하는 Consumer를 등록

최종 처리에서 average 사용 시 요소 없는 경우를 대비하는 방법
- isPresent() 메소드가 true를 리턴할 때만 집계값을 얻는다.
- orElse() 메소드로 집계값이 없을 경우를 대비해서 디폴트 값을 정해놓는다.
- ifPresent() 메소드로 집계값이 있을 경우에만 동작하는 Consumer 람다식을 제공한다.
요소 커스텀 집계
스트림이 제공하는 메소드
- 스트림은 기본 집계 메소드인 sum(), average(), count(), max(), min()을 제공하지만, 다양한 집계 결과물을 만들 수 있도록 reduce() 메소드도 제공
- reduce()는 스트림에 요소가 없을 경우 예외가 발생하지만, identity 매개값이 주어지면 이 값을 디폴트 값으로 리턴
요소 수집
필터링한 요소 수집
- Stream의 collect(Collector<T,A,R> collector) 메소드는 필터링 또는 매핑된 요소들을 새로운 컬렉션에 수집하고, 이 컬렉션을 리턴
- 매개값인 Collector는 어떤 요소를 어떤 컬렉션에 수집할 것인지를 결정
- 타입 파라미터의 T는 요소, A는 누적기accumulator, 그리고 R은 요소가 저장될 컬렉션

요소 그룹핑
- Collectors.groupingBy () 메소드에서 얻은 Collector를 collect() 메소드를 호출할 때 제공
- groupingBy()는 Function을 이용해서 T를 K로 매핑하고, K를 키로 해 List<T>를 값으로 갖는 Map 컬렉션을 생성

- Collectors.groupingBy() 메소드는 그룹핑 후 매핑 및 집계(평균, 카운팅, 연결, 최대,최소, 합계)를 수행할 수 있도록 두 번째 매개값인 Collector를 가질 수 있음

요소 병렬 처리
동시성과 병렬성
- 동시성: 멀티 작업을 위해 멀티 스레드가 하나의 코어에서 번갈아 가며 실행하는 것
- 병렬성: 멀티 작업을 위해 멀티 코어를 각각 이용해서 벙렬로 실행하는 것
- 데이터 병렬성: 전체 데이터를 분할해서 서브 데이터셋으로 만들고 이 서브 데이터셋들을 병렬 처리해서 작업을 빨리 끝내는 것
- 작업 병렬성: 서로 다른 작업을 병렬 처리하는 것
포크조인 프레임워크
- 포크 단계: 전체 요소들을 서브 요소셋으로 분할하고, 각각의 서브 요소셋을 멀티 코어에서 병렬로 처리
- 조인 단계: 서브 결과를 결합해서 최종 결과를 만들어냄
- 포크조인 프레임워크는 ExecutorService의 구현 객체인 ForkJoinPool을 사용해서 작업 스레드를 관리

병렬 스트림 사용
- 자바 병렬 스트림은 백그라운드에서 포크조인 프레임워크가 사용하므로 병렬 처리 용이
- parallelStream() 메소드는 컬렉션(List, Set)으로부터 병렬 스트림을 바로 리턴
- parallel() 메소드는 기존 스트림을 병렬 처리 스트림으로 변환
병렬 처리 성능에 영향을 미치는 요인
- 요소의 수와 요소당 처리 시간
- 스트림 소스의 종류
- 코어(Core)의 수
'자바' 카테고리의 다른 글
자바 - 네트워크 입출력 (0) | 2023.01.31 |
---|---|
자바 - 데이터 입출력 (0) | 2023.01.30 |
자바 - 람다식 (0) | 2023.01.27 |
자바 - 컬렉션 자료구조 (0) | 2023.01.25 |
자바 - 멀티 스레드 (0) | 2023.01.25 |