[Stream] 집계, Optional 클래스, 커스텀 집계(reduce)
- 프로그래밍 언어/Java
- 2019. 9. 19. 11:24
기본 집계 메소드
- 최종 처리 기능
- 요소들을 처리해서 카운팅, 합계, 평균값, 최대값, 최소값 등 하나의 값으로 산출
- 대량의 데이터를 가공해서 축소하는 리덕션.
기본 집계 메소드 예제
package Stream.middleprocess.zipgue;
import java.util.Arrays;
public class AggregateExample {
public static void main(String[] args) {
//배열선언
int[] temp = new int[] {
1,2,3,4,5
};
//카운트
long count = Arrays.stream(temp).filter(n -> n%2 ==0)
.count();
System.out.println("2의 배수 개수 : "+count);
//합계
long sum = Arrays.stream(temp).filter(n->n%2==0)
.sum();
System.out.println("2의 배수의 합 : "+sum);
//평균
double avg = Arrays.stream(temp)
.filter(n->n%2==0)
.average()
.getAsDouble();
System.out.println("2의 배수의 평균 : "+avg);
//최대
int max = Arrays.stream(temp)
.filter(n -> n%2==0)
.max()
.getAsInt();
System.out.println("2의 배수 최대값 : "+max);
//최소
int min = Arrays.stream(temp)
.filter(n->n%2==0)
.min()
.getAsInt();
System.out.println("2의 배수 최소값 : "+min);
}
}
Optional 클래스
- 자바 8에서 추가한 java.util 패키지의 Optional, OptionalDouble, OptionalInt, OptionalLong 클래스 타입.
- 값 기반 클래스(value-based class)
- 값을 얻기 위해서는 get(), getAsDouble(), getAsInt(), getAsLong() 메소드를 호출하면 됨.
- 단순히 집계 값만 저장하는 것이 아닌, 집계값이 존재하지 않을 경우 디폴트 값을 설정할 수 있고, 집계값을 처리하는 Consumer도 등록할 수 있다.
Optional 클래스의 메소드들
리턴 타입 | 메소드(매개변수) | 설명 |
boolean | isPresent() | 값이 저장되어 있는지 여부 |
T double int long |
orElse(T) orElse(double) orElse(int) orElse(long) |
값이 저장되어 있지 않을 경우 디폴트 값 지정 |
void |
ifPresent(Consumer) ifPresent(DoubleConsumer) ifPresent(IntConsumer) ifPresent(LongConsumer) |
값이 저장되어 있을 경우 Consumer에서 처리 |
예제 : 스트림에 값이 없는 경우.
List<Integer> list = new ArrayList<>();
double avg = list.stream()
.mapToInt(Integer::intValue)
.peek(p -> System.out.println(p))
.average()
.getAsDouble();
- list 컬렉션에는 아무것도 들어있지 않다. 그렇게 stream을 반환하면 역시 아무것도 없는 스트림이 반환된다.
- 그렇게 되면 average() 메소드를 호출후 그 값을 꺼내려(getXXX() 메소드 호출) 했을 때 어떻게될까????
-> 값이 없으면 에러가남.( java.util.NoSuchElementException)
- 그렇기 때문에 예외를 피하는 경우 3가지가 있다.
예제 : Optional 클래스를 사용할 때 예외를 피하는 3가지
import java.util.*;
public class OptionalException {
public static void main(String[] args) {
List<Integer> list = new ArrayList<>();
//방법 1
OptionalDouble optional = list.stream()
.mapToInt(Integer::intValue)
.average();
if(optional.isPresent())
System.out.println("방법1_평균 : "+optional.getAsDouble());
else
System.out.println("방법1_평균 : "+0.0 );
//방법2
double avg = list.stream()
.mapToInt(Integer::intValue)
.average()
.orElse(0.0);
System.out.println("방법2_평균 : "+avg);
//방법3 : 출력결과 안나옴. 없으면 행위자체를 안하는거나 마찬가지
list.stream()
.mapToInt(Integer::intValue)
.average()
.ifPresent(a->System.out.println("방법3_평균 : "+a));
}
}
방법 1. average까지 계산 후 isPresent() 메소드를 통해 값이 있는지 확인하여 분기한다
방법 2. orElse() 메소드를 이용해서 디폴트 값을 설정하여 값을 불러온다.
방법 3. ifPresent() 메소드를 이용하여 값이 있는 경우만 람다식을 실행한다.
커스텀 집계
- 기본 집계 메소드 외에도 프로그램화해서 다양한 집계 결과물을 만들 수 있도록 reduce() 제공.
- reduce(default value, XXXOperator)
import java.util.*;
import Stream.Student;
public class ReductionExample {
public static void main(String[] args) {
List<Student> studentList = Arrays.asList(
new Student("가나다", 30),
new Student("라마바", 20),
new Student("사아자", 10)
);
//studentList = new ArrayList<Student>();
int sum1 = studentList.stream().mapToInt(Student::getScore).sum();
int sum2 = studentList.stream().map(Student::getScore)
.reduce((a,b) -> a+b).get(); //스트림이 없을 경우엔 NoSuchElementException
int sum3 = studentList.stream().map(Student::getScore).reduce(0, (a,b)->a+b);
System.out.println("sum1 : "+sum1);
System.out.println("sum2 : "+sum2);
System.out.println("sum3 : "+sum3);
}
}
'프로그래밍 언어 > Java' 카테고리의 다른 글
[람다식] Java 함수형 인터페이스 @FunctionalInterface (0) | 2019.10.26 |
---|---|
[Stream] 수집, collect() 메소드, Collectors (0) | 2019.10.11 |
[Java 알고리즘] x만큼 간격이 있는 n개의 숫자, 프로그래머스 level1 (0) | 2019.09.18 |
[Stream] 정렬(sort), 루핑(peek, forEach, 매칭(allMatch, anyMatch, noneMatch) (0) | 2019.09.18 |
[Stream] 필터링, 매핑( flatMapXX(), mapXX(), boxed(), distinct(), filter() ) 관련 스트림 메소드 (0) | 2019.09.17 |