[Java] 스트림 API

sobam·2022년 10월 11일
0

자바

목록 보기
12/18
post-thumbnail

📔 학습한 내용을 정리하기 위해 작성하는 게시글입니다.

스트림 API란?


  • 데이터의 흐름을 가리켜 스트림이라고 한다.
    (데이터가 여러 개가 있어야 흐름을 만들 수 있기 때문에 스트림 데이터 소스로는 배열, 컬렉션 등이 주로 사용됨)

  • 스트림 데이터는 데이터 소스에서 추출한 연속적인 데이터이며, 스트림은 이런 연속적인 데이터의 흐름을 반복적으로 처리하는 기능이다.

  • 스트림 API를 이용하면 배열, 컬렉션, 파일에 저장된 데이터 등의 자료를 모두 같은 방식의 메서드로 호출하여 다룰 수 있다. (자료의 추상화)

자바에서는 많은 양의 데이터를 저장하기 위해 배열, 컬렉션을 사용하는데, 저장된 데이터에 접근하기 위해서 반복문이나 반복자(iterator)를 사용해 매번 새로운 코드를 작성함.
→ 길이가 너무 길고 코드의 재사용이 거의 불가능하다는 단점
→ 이러한 문제점을 극복하기 위해서 Java SE 8부터 스트림(stream) API를 도입

Java SE 8부터 추가된 stream API는 입출력 스트림(I/O stream)과는 전혀 다른 개념이다.



스트림 API 특징


  1. 외부 반복을 통해 작업하는 컬렉션과는 달리 내부 반복(internal iteration)을 통해 작업을 수행한다.

  2. 재사용이 가능한 컬렉션과는 달리 단 한 번만 사용할 수 있다.

  3. 원본 데이터를 변경하지 않는다.

  4. 필터-맵(filter-map) 기반의 API를 사용하여 지연(lazy) 연산을 통해 성능을 최적화한다.

  5. parallelStream() 메서드를 통해 손쉬운 병렬 처리를 지원한다.

  6. 자료의 대상과 관계없이 동일한 연산을 수행한다.

  7. 디버그가 힘들다.

java.util.stream 패키지의 멤버이며, BaseStream 인터페이스를 부모로 하여 네 종류의 스트림을 제공한다. (Stream, IntStream, LongStream, DoubleStream)



스트림 API 동작 흐름


스트림 API는 다음과 같이 세 가지 단계에 걸쳐서 동작한다.

  1. 스트림 생성
  2. 중개 연산 (스트림 변환)
  3. 최종 연산 (스트림 사용)

1. 스트림 생성

스트림 API는 다음과 같은 다양한 데이터 소스에서 생성할 수 있다.

1. 컬렉션(Collection)

ArrayList<Integer> list = new ArrayList<Integer>();
Stream<Integer> stream = list.stream();

2. 배열(Arrays)

String[] arr = new String[]{"1", "2", "3", "4"};
Stream<String> stream = Arrays.stream(arr);

3. 가변 매개변수(variable parameter)

Stream<Double> stream = Stream.of(4.2, 2.5, 3.1, 1.9);

4. 지정된 범위의 연속된 정수

IntStream stream = IntStream.range(1, 4);

5. 특정 타입의 난수들

IntStream stream = new Random().ints(4);

6. 람다 표현식

IntStream stream = Stream.iterate(2, n -> n + 2); // 2, 4, 6, 8, 10, ...

7. 파일

String<String> stream = Files.lines(Path path);

8. 빈 스트림

Stream<Object> stream = Stream.empty();

2. 중개 연산(intermediate operation)

자료를 거르거나 변경하여 또 다른 자료를 내부적으로 생성한다.

  • filter() : 조건을 넣고 그 조건에 맞는 참인 요소만을 추출

  • distinct() : 중복된 요소가 제거된 새로운 스트림 반환
    (내부적으로 Object 클래스의 equals() 메서드를 사용하여 요소의 중복을 비교함)

  • map() : 조건에 맞는 요소 반환

  • sorted() : 데이터를 조건에 따라 정렬


2. 최종 연산(terminal operation)

최종연산으로 중간 연산 결과를 출력한다.(마지막에 한 번 호출됨) 최종 연산은 스트림의 자료를 소모하면서 연산을 수행하기 때문에 최종 연산이 수행된 이후 해당 스트림은 사용할 수 없다.

  • forEach() : 요소를 하나씩 꺼내옴
  • count() : 요소 개수
  • sum() : 요소의 합
  • average() : 요소의 평균
  • min() : 요소의 최솟값
  • max() : 요소의 최댓값
  • reduce() : 정의된 연산이 아닌 프로그래머가 직접 지정하는 연산을 적용
    JDK에서 제공하는 reduce() 메서드의 정의는 다음과 같다.
    T reduce(T identify, BinaryOperator<T\> accumulator)
    내가 만듦


스트림 활용


//배열의 값 중 홀수만 골라 합을 구하는 예제
import java.util.Arrays;
import java.util.stream.IntStream;

public class Ex01_Stream1 {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3, 4, 5};
		
		//1. 스트림 생성 - 배열을 데이터 소스로 스트림 생성
		IntStream stm1 = Arrays.stream(arr);
		
		//2. 중개 연산 - 매개변수를 하나씩 받아 나머지가 1인지 검사하여 참인 값만 반환
		IntStream stm2 = stm1.filter(n -> n%2 == 1);
		
		//3. 최종 연산 - 모든 데이터의 값을 더함
		int sum = stm2.sum();
		System.out.println(sum);
	}
}
import java.util.Arrays;

public class Ex02_Pipeline {
	public static void main(String[] args) {
		int[] arr = {1, 2, 3, 4, 5};
		
		//Pipeline 구성
		int sum = Arrays.stream(arr)
				.filter(n -> n%2 == 1)
				.sum();
		
		System.out.println(sum);
	}
}

. 으로 연계할 수 있게 하는 방법을 파이프라인이라고 한다.



🔔 Reference

<Do it! 자바 프로그래밍 입문>
<이재환의 자바 프로그래밍 입문>
http://www.tcpschool.com/java/java_io_stream
https://jeong-pro.tistory.com/165
https://wakestand.tistory.com/419
https://kwangkyun-world.tistory.com/entry/Java-Stream-%EC%A0%95%EB%A6%AC%EA%B8%80

0개의 댓글

관련 채용 정보