본문 바로가기

프로그래밍/Java

java8 변경사항 - 스트림API 최종연산

스트림의 최종연산

스트림 API에서 중간 연산으로 변환된 스트림은 아래의 최종연산을 통해 요소를 소모하여 결과를 표시합니다.
지연(lazy) 되어있던 모든 중개 연산들이 최종 연산싯에 모두 수행됩니다.
최종연산 이후 모든 요소를 소모하고 난 후에는 해당 스트림을 사용할 수 없게 됩니다.

1. 요소 출력

forEach(): 스트림의 각 요소를 소모하여 명시된 동작을 수행한다.
반환타입은 void여서 보통 출력하는 용도로 사용한다.

Stream<String> stream = Stream.of("A", "B", "C", "D");
stream.forEach(System.out::println);    //ABCD

2. 요소 소모

reduce(): 첫번째와 두번째 요소로 연산을 수행 후 그결과와 세번째 요소로 연산을 수행하는식으로 모든 요소를 소모하여 연산을 수행하고 그 결과를 반환한다.

Stream<String> stream = Stream.of("A", "B", "C", "D");
Optional<String> result = stream.reduce((s1, s2) -> s1 + "," + s2);
result.ifPresent(System.out::print);   // A,B,C,D

3. 요소 검색

조건에 일치하는 첫번째 요소를 반환하는 메서드로 findFirst()와 findAny()메서드가 있다.
두 메서드는 모두 비어있는 스트림에서는 Optional 객체를 반환하며 병렬 스트림인 경우에는 findFirst()대신 findAny()를 사용해야 한다.

IntStream stream = IntStream.of(1, 2, 4, 3, 5, 5, 6);
System.out.println("result = " + stream.sorted().findFirst().getAsInt()); //1

4. 요소 검사

anyMatch(): 스트림의 일부 요소가 조건을 만족하는 경우 true 반환
allMatch(): 스트림의 모든 요소가 조건을 만족하는 경우 true 반환
noneMatch(): 스트림의 모든 요소가 조건을 만족하지 않을 경우 ture 반환
이 메서드들은 모두 매개변수로 Predicate를 요구하며, 연산 결과로 boolean을 반환한다.

IntStream stream = IntStream.of(30, 40, 60, 90);
IntStream stream2 = IntStream.of(30, 40, 60, 90);
System.out.println(stream.anyMatch(n -> n > 60));   //true;
System.out.println(stream2.allMatch(n -> n > 60));   //false;

5. 요소 통계

count(): 총 개수를 long 타입의 값으로 반환
min(): 최소값 반환
max(): 최대값 반환

IntStream stream = IntStream.of(30, 40, 60, 90);
System.out.println(stream.max().getAsInt());   //90
IntStream stream2 = IntStream.of(30, 40, 60, 90);
System.out.println(stream2.min().getAsInt());   //30
IntStream stream3 = IntStream.of(30, 40, 60, 90);
System.out.println(stream3.count());   //4

6. 요소 연산

sum(): 합 반환
average(): 평균 반환

IntStream stream = IntStream.of(30, 40, 60, 90);
System.out.println(stream.sum());   //220
IntStream stream2 = IntStream.of(30, 40, 60, 90);
System.out.println(stream2.average().getAsDouble());   //55.0

7. 요소 수집

collection(): 스트림의 요소를 수집하는 최종연산으로 리듀싱(reducing)과 유사하다.
어떻게 수집할 것인가에 대한 방법이 정의되어있는 Collector대로 수집한다.
스트림요소의 수집 용도는 크게 4가지로 아래와 같다.

7.1 스트림을 배열이나 컬렉션으로 변환

toCollection(), toList(), toSet(), toMap(): 스트림을 컬렉션으로 변환
toArray(): 스트림을 배열로 변환

Stream<String> stream = Stream.of("java", "cpp", "python","php");
List<String> list = stream.collect(Collectors.toList());
for (String S : list) {
    System.out.print(S+" ");    // java cpp python
}

7.2 통계

counting(), maxBy(), minBy(), summingInt(), averagingInt(): 요소의 통계, 연산 메소드와 같은동작을 수행하는 메서드

Stream<String> strStream = Stream.of("A","B","C");
long count = strStream.collect(Collectors.counting());
System.out.println("count = " + count); //3

Person p1 = new Person("철수",17);
Person p2 = new Person("김씨",15);
Person p3 = new Person("박씨",21);
List<Person> persons = Arrays.asList(p1,p2,p3);
Optional<Person> oldPerson = persons.stream().collect(Collectors.maxBy(Comparator.comparingInt(Person::getAge)));
System.out.println("oldPerson = " + oldPerson.get().getName()); //박씨

7.3 요소의 소모와 같은 동작 수행

//reducing()
IntStream intStream = IntStream.of(4, 2, 1, 3);
Optional<Integer> sum = intStream.boxed().collect(Collectors.reducing(Integer::sum));
System.out.println("sum = " + sum.get());   //10

//joining()
Person p1 = new Person("철수",17);
Person p2 = new Person("김씨",15);
Person p3 = new Person("박씨",21);
List<Person> persons = Arrays.asList(p1,p2,p3);
String personNames = persons.stream().map(Person::getName).collect(Collectors.joining(","));
System.out.println("personNames = " + personNames); //철수,김씨,박씨

7.4 요소의 그룹화와 분할

groupingBy(): 요소의 그룹화
partitioningBy(): 요소의 분할

Stream<String> stream = Stream.of("java", "cpp", "python","php");
Map<Boolean, List<String>> patition =  
stream.collect(Collectors.partitioningBy(s -> (s.length() % 2) == 0));
List<String> oddLengthList = patition.get(false);
List<String> evenLengthList = patition.get(true);
System.out.println("홀수 길이 str: "+oddLengthList);    //cpp, php
System.out.println("짝수 길이 str: "+evenLengthList);   //java, python

스트림의 변환

스트림간의 변환메서드의 종류를 간단하게 정리하였다.

  1. 스트림 -> 기본형 스트림
    mapToInt(ToIntFunction mapper)
    mapToLong(ToLongFunction mapper);
    mapToDouble(ToDoubleFunction mapper);
  2. 기본형 스트림 -> 스트림
    boxed()
    mapToObj(DoubleFunction mapper)
  3. 기본형 스트림 -> 기본형 스트림
    asLongSteram()
    asDoubleStream()
  4. 스트림 -> 부분 스트림
    skip(long n)
    limit(long maxSize)
  5. 두개의 스트림 - > 스트림
    concat(Streama, Stream b)
    concat(IntStream a, IntStream b)
    concat(LongStream a, LongStream b)
    concat(DoubleStream a, DoubleStream b)
  6. 스트림의 스트림 -> 스트림
    flatMap(Function mapper)
    flatMapToInt(Function mapper)
    flatMapToLong(Function mapper)
    flatMapToDouble(Function mapper)
  7. 스트림 <-> 병렬 스트림
    parallel() //스트림 -> 병렬 스트림
    sequential() //병렬 스트림 -> 스트림
  8. 스트림 -> 컬렉션
    collect(Collectors.toList())
    collect(Collectors.toSet())
  9. 컬렉션 -> 스트림
    stream()
  10. 스트림 -> Map
    collect(Collectors.toMap(Function key, function value))
  11. 스트림 -> 배열
    toArray()

'프로그래밍 > Java' 카테고리의 다른 글

java8 - time  (0) 2020.03.10
java8 - Optional  (0) 2020.02.23
Java8 변경사항 - 스트림API 중간연산  (0) 2020.02.07
Java8 변경사항 - 스트림API 특징과 생성  (0) 2020.02.01
Java8 변경사항 - 람다 표현식  (0) 2020.01.29