모르지 않다는 것은 아는것과 다르다.

Java

Stream 응용

채마스 2022. 3. 6. 23:10

Stream 의 다양한 종결처리

Max

  • Optional max(Comparator<? super T> comparator);
  • Stream 안의 데이터 중 최대값을 반환. Stream이 비어있다면 빈 Optional을 반환한다.
Optional<Integer> max = Stream.of(5, 3, 6, 2, 1)
            .max(Integer::compareTo);
System.out.println(max.get());
  • 반환값이 Optional 이기 때문에 get() 을 이용해서 꺼낸다.
BigDecimal maxErroredAmount = orders.stream()
            .filter(order -> order.getStatus() == OrderStatus.ERROR)
            .map(Order::getAmount)
            .max(BigDecimal::CompareTo)
            .orElse(BigDecimal.ZERO);
  • 주문 목록에서 에러가 있는 주문들의 금액을 비교해서 가장큰 값을 반환할 수 있다.
  • max 의 반환값이 Optional 이기 때문에 orElse 으로 null 처리를 할 수 있다.

 

Min

  • Optional min(Comparator<? super T> comparator);
  • Stream 안의 데이터 중 최소값을 반환. Stream이 비어있다면 빈 Optional을 반환한다.
Optional<Integer> max = Stream.of(5, 3, 6, 2, 1)
            .min(Integer::compareTo);
            .orElse(10);
System.out.println(firstUser);

 

count

  • long count();
  • Stream 안의 데이터의 개수를 반환한다.
long positiveIntegerCount = Stream.of(1, -4, 5, -3, 6)
            .filter(x -> x > 0)
            .count();

 

allMatch

  • boolean allMatch(Predicate<? super T> predicate);
  • Stream 안의 모든 데이터가 predicate을 만족하면 true 를 반환한다.
boolean allPostive = numbers.stream()
                .allMatch(number -> number > 0);
System.out.println("Are all numbers positive: " + allPostive);

 

anyMatch

  • boolean anyMatch(Predicate<? super T> predicate);
  • anyMatch – Stream 안의 데이터 중 하나라도 predicate을 만족하면 true 를 반환한다.
boolean anyNegative = numbers.stream()
                .anyMatch(number -> number < 0);
System.out.println("Is any number negative: " + anyNegative);

 

findFirst

  • Optional findFirst();
  • Stream 안의 첫번째 데이터를 반환한다.
  • Stream이 비어있다면 비어있는 Optional을 반환한다.
Optional<Integer> anyNegativeInteger = Stream.of(3, 2, -5, 6)
            .filter(x -> x < 0)
            .findAny();
System.out.println(anyNegativeInteger.get());

 

findAny

  • Optional findAny();
  • Stream 안의 아무 데이터나 리턴한다.
  • 순서가 중요하지 않고 Parallel Stream을 사용할 때 최적화를 할 수 있다.
  • 마찬가지로 Stream이 비어있다면 빈 Optional을 반환한다.
Optional<Integer> firstPositiveInteger = Stream.of(-3, -2, -5, 6)
            .filter(x -> x > 0)
            .findFirst();
System.out.println(firstPositiveInteger.get());

 

reduce

  • 주어진 함수를 반복 적용해 Stream 안의 데이터를 하나의 값으로 합치는 작업을 한다.
  • Optional reduce(BinaryOperator accumulator);
    • 주어진 accumulator를 이용해 데이터를 합친다.
    • Stream이 비어있을 경우 빈 Optional을 반환한다.
List<Integer> numbers = Arrays.asList(1, 4, -2, -5, 3);
int sum = numbers.stream()
        .reduce((x, y) -> x + y)
        .get();

int min = numbers.stream()
        .reduce((x, y) -> x > y ? x : y)
        .get();
  • T reduce(T identity, BinaryOperator accumulator);
    • 주어진 초기값과 accumulator를 이용한다.
    • 초기값이 있기 때문에 항상 반환값이 존재한다. -> 반환값이 Optional 이 아니다.
int product = numbers.stream()
                .reduce(1, (x, y) -> x * y);

List<String> numberStrList = Arrays.asList("3", "2", "5", "-4");
int sumOfNumberStrList = numberStrList.stream()
        .map(Integer::parseInt)
        .reduce(0, (x, y) -> x + y);
  • 위와 같이 초기값이 있기 때문에 반환값이 Optional 이 아니다.
  • * U reduce(U identity, BiFunction<U, ? super T, U> accumulator, BinaryOperator combiner);*
    • 합치는 과정에서 타입이 바뀔 경우 사용한다.
    • Map + reduce로 대체 가능하다.
    • 초기값이 있기 때문에 항상 반환값이 존재한다. -> 반환값이 Optional 이 아니다.
int sumOfNumberStrList2 = numberStrList.stream()
                .reduce(0, (number, str) -> number + Integer.parseInt(str), (num1, num2) -> num1 + num2);
  • map, reduce 를 한번에 처리할 수 있다.
Order order1 = new Order()
        .setId(1001L)
        .setOrderLines(Arrays.asList(
                new OrderLine().setAmount(BigDecimal.valueOf(1000)),
                new OrderLine().setAmount(BigDecimal.valueOf(2000))));
Order order2 = new Order()
        .setId(1002L)
        .setOrderLines(Arrays.asList(
                new OrderLine().setAmount(BigDecimal.valueOf(2000)),
                new OrderLine()
                .setAmount(BigDecimal.valueOf(3000))));
Order order3 = new Order()
        .setId(1002L)
        .setOrderLines(Arrays.asList(
                new OrderLine().setAmount(BigDecimal.valueOf(1000)),
                new OrderLine().setAmount(BigDecimal.valueOf(2000))));
List<Order> orders = Arrays.asList(order1, order2, order3);

BigDecimal sumOfAmount = orders.stream()
        .map(Order::getOrderLines) // Stream<List<OrderLine>>
        .flatMap(List::stream) // Stream<OrderLine>
        .map(OrderLine::getAmount) //Stream<BigDecimal>
        .reduce(BigDecimal.ZERO, BigDecimal::add);
  • flatMap 을 사용해서 Stream 형태로 타입을 바꿔준다.
  • 최종적으로 reduece 를 사용해서 값들의 합을 구한다. 초기값은 BigDecimal.ZERO 로 설정해 준다.

 

 

REFERENCES

  • 이승환님의 JAVA Stream

'Java' 카테고리의 다른 글

Collectors (JAVA STREAM)  (0) 2022.03.06
LazyEvaluation,Curry,IntStream  (0) 2022.03.06
함수형 인터페이스  (0) 2022.02.26
제네릭  (0) 2022.02.26
접근 지정자  (0) 2022.02.26