💻IT/Java

[Java] Java 8 Stream API

gom20 2021. 12. 3. 19:03

참고

https://www.baeldung.com/java-8-streams-introduction

https://www.baeldung.com/java-8-streams

Stream API란?

JAVA8의 새로운 기능

Stream 기능에는 시퀀셜한 데이터를 처리하는 클래스들이 포함되어있음

 

Stream 생성

collection이나 array의 stream() 

Stream의 of() 

String[] arr = new String[]{"a", "b", "c"};
Stream<String> stream = Arrays.stream(arr);
stream = Stream.of("a", "b", "c");

 

Empty Stream

Stream.empy()로 element가 없는 stream을 생성할 수 있다. 

Stream<String> streamEmpty = Stream.empty();

Stream of Collection 

Collection, List, Set 어떤 타입이든 스트림을 생성할 수 있다. 

List<Integer> list = Arrays.asList(3, 2, 7, 4);
Stream<Integer> stream = list.stream();

Stream of Array

Array도 Stream의 소스가 될 수 있다.

Stream<String> streamOfArray = Stream.of("a", "b", "c");

Stream.builder()

타입을 명시하지 않으면 Stream<Object>로 생성된다.

Stream<Integer> stream = Stream.<Integer>builder().add(1).add(2).add(3).build();

Stream.iterate()

Stream<Integer> stream = Stream.iterate(1, n -> n+1).limit(10);
System.out.println(stream.toList().toString());

stream = Stream.iterate(2, n -> n+2).limit(10);
System.out.println(stream.toList().toString());

primitive 타입의 Stream

  • IntStream
  • LongStream
  • DoubleStream
IntStream intStream = IntStream.range(1, 5);
intStream.map(x -> x*10).toArray();

 

Stream 연산

연산은 아래와 같이 나눌 수 있다.

  • 중간 연산 (Stream 객체를 리턴) -> chaining 허용
  • 최종 연산 (정의된 타입으로 리턴)

스트림은 소스 데이터를 변경하지 않는다. 

아래 예시에서 distinct()함수는 중간 연산이며 이전 stream에서 중복을 제거하여 새로운 stream을 생성한다.

count()는 최종 연산이며 stream의 size를 리턴한다.

List<String> list = Arrays.asList("a", "a", "b", "c");
System.out.println(list.stream().distinct().count());
System.out.println(list.toString());

 

Iterating

StreamAPI로 반복문 기능을 구현할 수 있다.

boolean isExist;
for(String s : list){
    if(s.contains("a")){
        isExist = true;
        break;
    }
}

isExist = list.stream().anyMatch(element -> element.contains("a"));

Filtering

filter() 함수는 조건을 만족하는 값만 취할 수 있게 해준다. 

list에서 "a"문자열을 포함하는 element만 가지는 stream을 생성하여 해당 사이즈를 리턴

list.stream().filter(element -> element.contains("a")).count()

Mapping

Stream의 element에 특정 함수를 적용하여 값을 변환시키고 이를 다시 새로운 Stream으로 반환하고자 할 때 map() 함수를 사용한다. 

문자열을 Long형으로 변환한 예시

List<String> list = Arrays.asList("1", "2", "3", "4");
System.out.println(list.stream().map(element -> Double.parseDouble(element)).toList());

Matching

StreamAPI는 특정 조건에 따라 시퀀스의 element를 검증할 수 있는 편리한 메소드를 제공한다.

  • anyMatch() 적어도 하나의 element가 조건에 부합하면 true 
  • allMatch() 모든 element가 조건에 부합해야 true
  • noneMatch() 모든 element가 조건에 부합하지 않아야 true
List<Integer> list = Arrays.asList(1, 2, 3, 4);
System.out.println(list.stream().allMatch(element -> element < 5));
System.out.println(list.stream().anyMatch(element -> element < 2));
System.out.println(list.stream().noneMatch(element -> element < 2));
System.out.println(list.stream().noneMatch(element -> element > 4));

Reduction

reduce 메소드를 이용해 Stream의 element를 하나씩 줄여가며 누적 연산을 지원한다.

List<Integer> list = Arrays.asList(3, 2, 7, 4);
int max = list.stream().reduce((a, b) -> a > b? a : b).get();
int min = list.stream().reduce((a, b) -> a < b? a : b).get();
int sum = list.stream().reduce((a, b) -> a + b).get();
System.out.println("max: " + max + ", min: " + min + ", sum: " + sum);

Collectiong

collect 함수로 stream을 Collection 이나 맵으로 변환 할 수 있다. 

List<Integer> list = Arrays.asList(3, 2, 7, 4);
List<String> strList = list.stream().map(element -> String.valueOf(element) + "위").collect(Collectors.toList());
System.out.println(strList);