자바(Java)

자바 스트림(stream)

넉우리 2023. 2. 4. 22:37
반응형

스트림(Stream)

스트림은 배열, 컬렉션, 파일 등 여러 데이터들을 다루는 자료형에서 데이터를 하나씩 참조하여 처리 가능한 기능을 말한다. 람다를 사용할 수 있는 기술이다. 반복문이나 iterator를 사용하지 않아도 된다. JDK 1.8부터 나왔다.

이를 통해 for문의 사용을 줄여서 코드를 간결하게 할 수 있다.

특징으로는

  • 원본 데이터를 사용하지만 변경은 불가능하다.
  • 일회용으로 사용하므로 처리 후 재사용이 불가능하다.
  • 내부적으로 반복 및 병렬처리가 가능하다.
  • 기본 데이터을 처리하기 위한 래퍼 스트림(Int,Double,LongStream)도 지원한다.

Stream은 크게 Stream 생성, 중개연산, 최종연산의 3단계로 진행된다.

데이터소스객체.Stream생성().중개연산().최종연산(); 이런식으로 쓰인다.

스트림 객체는 최종연산을 하면 더 이상 스트림연산을 할 수 없고 종료가 된다. 그 객체로 더 하려고 하면 오류가 뜬다.

각 단계의 자주 쓰이는 것들을 알아보자.

스트림 생성

종류 사용 예시 설명
배열 스트림 Stream s1 = Arrays.stream(arr); arr은 위에 선언된 배열이라고 가정
컬렉션 스트림 Steram s2 = l1.stream(); l1은 위에서 선언된 컬렉션이라고 가정
스트림 builder Stream b1 = Stream.builder().add(1).add("gef").add(7).build(); add로 원하는 값을 넣고 build로 스트림을 생성
스트림 generate
Stream g1 = Stream.generate( () -> "abc" ).limit(3);
람다를 통해 값을 넣은 스트림 생성
limit은 옆 행동을 반복한다는 뜻이다.
즉, 예시는 "abc"가 3개 있는 스트림을 생성한다.
스트림 iterate Stream i1 = Stream.iterate(5, n -> n * 2).limit(4); 5는 초기값이고 람다식을 한번씩 적용해서 4개의 값이 들어있는 스트림을 생성한다.
예시는 5,10,20,40이 있는 스트림을 생성한다.
기본 타입 스트림 IntStream s3 = Intstream.range(1,5); range는 연속적인 숫자를 만드는 함수다. 
예시는 1,2,3,4가 있는 스트림을 생성한다.

기본 데이터형을 다룰때는 Stream<Integer> list1 = list.stream();같이 래퍼클래스로 해준다.

 

중개연산

종류 사용 예시 설명
Filtering
IntStream s1 = IntStream.range(1, 10).
filter(n -> n % 2 == 0);
filter는 어떤 조건을 줘서 참인 요소들을 추출하는 것이다.
예시는 1~9중 짝수인걸 추출한다.
** distinct()라고 중복을 지워주는 메소드도 있다. **
Mapping IntStream s2 = IntStream.range(1, 10).map(n -> n + 1); map은 map 안의 연산을 요소별로 수행하는 것이다.
예시는 1~9에 1을 더한 스트림을 만든다.
** flatMap()라고 스트림요소가 배열인 경우 주어진 명령문을 적용한 새로운 스트림을 반환한다. **
Sorting s3.sorted(); sort는 stream을 정렬하는 것이다.
Splitting s4.limit(3);
// (5,1,2,4,6) -> (5,1,2)반환
s4.skip(3);
// (5,1,2,4,6) -> (4,6,)반환
limit()은 스트림에서 limit에 들어가는 수만큼의 새로운 스트림을 반환한다.
skip()은 스트림의 첫 요소부터 skip에 들어가는 수를 제외한 새로운 스트림을 반환한다.

 

최종연산

종류 사용 예시 설명
Sum int sum = IntStream.range(1, 5).sum(); 예시는 1~4의 값을 더하는 최종연산이다.
Average double average = IntStream.range(1, 5).average().getAsDouble(); 예시는 1~4의 값의 평균을 구하는 연산이다.
min int min = IntStream.range(1, 5).min().getAsInt(); Stream 값중 최솟값을 구하는 연산이다.
max int max = IntStream.range(1, 5).max().getAsInt(); Stream 값중 최댓값을 구하는 연산이다.
reduce s1.reduce((x, y) -> x + y).get(); map이랑 유사해 보이지만, reduce는 연쇄적으로 해서 데이터를 뽑아내는 연산이다.
anyMatch s1.anyMatch(n -> n % 2 == 1); 스트림의 일부 요소가 특정 조건 만족시 true 반환
allMatch s1.allMatch(n -> n % 2 == 1); 스트림의 모든 요소가 특정 조건 만족시 true 반환
noneMatch s1.noneMatch(n -> n % 2 == 1); 스트림의 모든 요소가 특정 조건 불만족시 true 반환
findFirst s1.findFirst(); 스트림 첫 요소 반환
forEach s1.forEach(System.out::println);
s1.forEach(num -> System.out.println("num = " + num));
해당 스트림 각 요소를 출력하는 연산이다. 람다식으로 출력형식을 정할 수도 있다.

 

** 입출력에서 스트림은 자바에서 입출력을 위해 두 대상을 연결하여 데이터를 송/수신하는데 사용되는 연결통로이다. 중간에 끊김없이 연속적으로 데이터를 송수신한다.

 

Optional 클래스

스트림 결과값을 반환받을 때 사용가능한 참조형 데이터 타입이다.

Null값으로 인한 예외를 회피할 수 있다. 특정 클래스가 참조변수인 경우에는 NullPointerException이 발생할 수 있어서 Null값에 대한 예외 처리를 해줘야한다. 

Optional 클래스는 모든 타입의 참조변수를 저장할 수 있고, 스트림과 비슷하게 기본 데이터형을 처리할 수 있는 래퍼클래스를 지원한다.

반응형