Back-end/이것이 자바다[신용권 한빛미디어]

기본 집계(sum(), count(), average(), max(), min())

Ho's log 2022. 6. 3. 18:15

기본집계()


집계(Aggregate)는 최종 처리 기능으로 요소들을 처리해서 카운팅, 합계, 평균값, 최대값, 최소값 등과 같이 하나의 값으로 산출하는 것을 말한다.

집계는 대량이 데이터를 가공해서 축소하는 리덕션(Reduction) 이라고 볼수 있다.

 

스트림이 제공하는 기본 집계

 

이 집계 메소드에서 리턴하는 OptionalXXX 는 자바 8에 추가한 java.util 패키지의 Optional, OptionalDouble, OptionallInt, OptionallLong 클래스 타입을 말한다.

이들은 값을 저장하는 값 기반 클래스(value-based class)들이다

이객체에서 값을 얻기 위해서는 getAsDouble(), getAsInt(), getAsLong() 을 호출하면 된다

package Stream;

import java.util.Arrays;

public class AggregateExample {
    public static void main(String[] args) {
        long count = Arrays.stream(new int[] {2,4,6,8,10}).filter(n->n%2 ==0).count();
        System.out.println("count : " + count);

        long sum = Arrays.stream(new int[] {1,2,3,4,5}).filter(predicate -> predicate % 2 == 0).sum();
        System.out.println("sum : " + sum);

        double average = Arrays.stream(new int[] {1,2,3,4,5}).filter(predicate -> predicate % 2 == 0).average().getAsDouble();
        System.out.println("average : " + average);

        int max = Arrays.stream(new int[] {1,2,3,4,5}).filter(predicate -> predicate % 2 == 0).max().getAsInt();
        System.out.println("max" + max);

        int min = Arrays.stream(new int[] {1,2,3,4,5}).filter(predicate -> predicate % 2 == 0).min().getAsInt();
        System.out.println("min" + min);

        int first = Arrays.stream(new int[] {1,2,3,4,5}).filter(predicate -> predicate % 2 == 0).findFirst().getAsInt();
        System.out.println("first" + first);
    }
}

 

Optional 클래스


Optional, OptionalDouble, OptionalInt, OptionalLong 클래스에 알아 보자

이 클래스들은 저장하는 값의 타입만 다를 뿐 제공하는 기능은 거의 동일하다.

Optional 클래스는 단순히 집계값만 저장하는 것이 아니라, 집계 값이 존재하지 않을 경우 디폴트 값을 설정 할 수도 있고,

집계 값을 처리하는 Consumer도 등록할 수 있다.

다음은 Optional 클래스들이 제공하는 메소드 

컬렉션의 요소는 동적으로 추가되는 경우가 많다. 

저장된 요소가 없을 경우 다음 코드는 어떻게 될까?

List<Integer> list = new ArrayList<>();
double avg = list.stream().mapToInt(Integer::intValue).average().getAsdouble();
System.out.println("평균 : " + avg);

 

요소가 없기 때문에 평균값도 있을 수 없다

NoSuchElementException 예외가 발생한다.

요소가  없을 경우 예외를 피하는 세가지 방법이 있다.

첫번재는 Optional 객체를 얻어 isPresent() 메소드로 평균값 여부를 확인 하는 것이다.

isPresent() 메소드가 true 를 리턴할때만 getAsDouble() 메소드로 평균값을 얻으면 된다.

 

OptionalDouble opitonal = list.stream().mapToInt(Integer::intValue).average();

if(opitonal.isPresnt()){
	System.out.println("평균 : " + optional.getAsDouble());
    

} else {

	System.out.println("평균 : " + 0.0); 
}

 

두 번재 방법은 orElse() 메소드로 디폴트 값을 정해 놓는다. 

평균값을 구할 수 없는 경우에는 orElse() 의 매개값이 디폴트 값이 된다

 

double avg = list.stream().mapToInt(Integer :: intValue).avaerage().orElse(0.0);

System.out.println("평균: " + avg );

 

세번재 방법은 ifPresent() 메소드로 평균값이 있을 경우에만 값을 이용하는 람다식을 실행 

list.stream().mapToInt(Integer::intValue).average().ifPresent(a->System.out.println("평균: " + a));
package Stream;

import java.util.ArrayList;
import java.util.List;
import java.util.OptionalDouble;

public class OptionalExample {

    public static void main(String[] args) {

        List<Integer> list = new ArrayList<>();

        /*
         * 예외 발생
         * 
         * double avg
         * =list.stream().mapToint(Integer::intValue).average().getAsDouble();
         * 
         */

        // 방법 1

        OptionalDouble OptionalDouble = list.stream().mapToInt(Integer::intValue).average();

        if (OptionalDouble.isPresent()) {
            System.out.println(OptionalDouble.getAsDouble());
        } else {
            System.out.println("No value");

        }

        // 방법 2
        double avg = list.stream().mapToInt(Integer::intValue).average().orElse(0);

        System.out.println("avg : " + avg);

        //방법3 
        list.stream().mapToInt(Integer::intValue).average().ifPresent(System.out::println);
        
    }

}