Stream이란?

스트림(stream)은 자바 8부터 추가 된 기능으로, 컬렉션에 저장한 엘리먼트들을 하나씩 순회하면서 처리할 수 있는 기능이다.
자바 8이전의 배열 또는 컬렉션을 다루는 방법은 'for','forEach'를 사용하여 엘리먼트를 꺼내서 다루는 방법이였다.
스트림을 이용하면 배열 또는 컬렉션을 함수 여러 개를 사용해서 결과를 쉽게 얻을 수 있으며
람다식과 함께 사용하면 컬렉션에 담긴 데이터 처리를 간결하게 표현할 수 있다.
List<String> stringList = new ArrayList<>(Arrays.asList("hello","world","stream"));​

rayList 클래스를 사용하여 String 타입의 요소를 가진 List를 생성한다.

생성자에 Arrays.asList() 메서드를 사용하여 "hello", "world", "stream" 요소를 포함하는 List를 생성하고,

이를 ArrayList의 생성자의 인수로 전달하여 ArrayList를 생성한다.

따라서 stringList 변수는 "hello", "world", "stream" 요소를 가진 ArrayList이다.

 

 

이전에 스트림을 이용하지 않던 방식

		for(String str: stringList) {
			System.out.println(str);
		}

>hello world stream

 

스트림을 이용한 방식

stringList.forEach(System.out::println);

>hello world stream


 

배열과 컬렉션 객체의 stream() 메소드를 활용한 스트림 생성

String[] sarr = {"java", "oracle", "jdbc"};

배열을 String이라는 타입으로 변환시킨다.

Stream<String> strStream1 = Arrays.stream(sarr);

strStream1.forEach(System.out::println);

>java oracle jdbc

 

 

주어진 코드에서는 Arrays.stream() 메서드를 사용하여 문자열 배열 sarr의 인덱스 0부터 1까지의 요소를 스트림으로 변환하고, 이를 strStream2 변수에 할당합니다. 그리고 forEach() 메서드를 사용하여 strStream2의 모든 요소를 출력합니다.

forEach() 메서드는 스트림의 각 요소에 대해 주어진 동작(action)을 수행합니다. 이 경우에는 각 요소를 System.out::println() 메서드로 출력하는 것입니다. 따라서 strStream2에 포함된 요소들이 출력됩니다.

스트림은 데이터의 처리를 병렬화하거나 최적화하기 위한 API이며, 요소를 소비(consume)하는 

터미널 연산(terminal operation)을 호출하기 전까지는 중간 연산(intermediate operation)만 수행하며, 실제 데이터를 처리하지 않습니다. 

따라서 forEach() 메서드를 호출하여 스트림의 모든 요소를 소비하면, 중간 연산에 의해 처리된 결과가 터미널 연산을 통해 출력되는 것입니다.

	Stream<String> strStream2 = Arrays.stream(sarr,0,2);
	strStream2.forEach(System.out::println);

> java oracle

 

	//컬렉션 스트림 생성
	List<String> stringList = Arrays.asList("html","css","javascript");
	
	//위에를 스트림으로 만들기
	Stream<String> strStream3 = stringList.stream();
	strStream3.forEach(System.out::print);
	
	//forEach는 컬렉션에도 작성되어 있어 Stream으로 만들지 않고 사용할 수 있다.
	stringList.forEach(System.out::println);
}

>

htmlcssjavascripthtml

css

javascript


 

Stream의 최종 연산

 

중간 연산을 통해 변환 된 스트림은 마지막의 최종 연산을 통해 각 요소를 소모하여 지연되었던 모든 중간연산이

최종 연산 시에 수행 된다.

 

 

forEach()

 

스트림의 모든 요소를 소모하여 지정 된 작업을 수행, 보통 스트림의 모든 요소를 출력하는 용도로 많이 사용된다.

		System.out.println("===== 스트림 요소 출력 =====");
		IntStream.range(1, 10).forEach(System.out::println);
		System.out.println();
더보기

===== 스트림 요소 출력 =====

1

2

3

4

5

6

7

8

9

 

reduce()

 

스트림의 요소를 하나씩 줄여가며 누적 연산을 수행한다.

		System.out.println("===== 요소 소모 결과 출력 =====");
		IntStream stream1 = IntStream.rangeClosed(1, 100);
		int sum = stream1.reduce(0, (a, b) -> a + b); // 1~100을 더한 결과
		System.out.println(sum);

주어진 코드에서는 IntStream.rangeClosed() 메서드를 사용하여 1부터 100까지의 정수를 가지는 스트림을 생성하고, reduce() 메서드를 사용하여 스트림의 모든 요소를 더합니다.reduce() 메서드는 스트림의 요소를 반복적으로 결합하여 하나의 결과를 도출합니다. 첫 번째 인수는 reduce() 메서드를 호출할 때 초기값으로 사용할 값을 전달하고,

두 번째 인수는 BinaryOperator<T> 타입의 함수형 인터페이스로, 스트림의 각 요소를 결합하는 방법을 정의합니다.

따라서 해당 코드에서는 초기값으로 0을 전달하고, 람다식으로 a와 b를 더하는 연산을 전달하여 모든 요소를 더한 결과를 얻습니다. 이때 reduce() 메서드는 스트림의 모든 요소를 순회하면서 연산을 수행하며, 최종 결과인 1부터 100까지의 합을 sum 변수에 저장합니다.따라서 출력 결과는 1부터 100까지의 정수를 더한 5050이 됩니다.

 

count()

 

요소의 개수를 long 타입으로 변환한다.

 

 

sum()

 

요소의 합계 반환

 

		IntStream stream5 = IntStream.of(99, 44, 55, 88, 77);
		System.out.println(stream5.count());

		IntStream stream6 = IntStream.of(99, 44, 55, 88, 77);
		System.out.println(stream6.sum());

 

of() 메서드

 

IntStream.of() 메서드는 전달된 인수를 가지고 IntStream을 생성한다.
IntStream은 기본형 int 요소를 연속적으로 처리하기 위한 스트림입니다.
IntStream.of() 메서드는 가변인자(variable arguments)를 사용하여 인수를 전달합니다. 즉, 인수의 개수에 제한이 없으며, 여러 개의 인수를 전달할 수 있습니다. 예를 들어, IntStream.of(1, 2, 3, 4, 5)와 같이 인수를 전달할 수 있습니다.
따라서 해당 코드에서는 IntStream.of() 메서드를 사용하여 99, 44, 55, 88, 77의 다섯 개의 요소를 가지는 IntStream을 생성합니다. 이후에는 count() 메서드를 사용하여 stream5 스트림의 요소 개수를 출력하고, sum() 메서드를 사용하여 stream6 스트림의 모든 요소를 더한 값을 출력합니다.

즉, of() 메서드는 주어진 인수를 가지고 IntStream을 생성하는 메서드입니다.
이를 통해 기본형 int 요소를 스트림으로 처리할 수 있습니다.

 

가장 스코어가 높은 학생도 찾기 가능!

 

Stream<StudentDTO> stream4 = Stream.of(new StudentDTO(1, 3, "유관순", 90), new StudentDTO(2, 1, "홍길동", 80),
new StudentDTO(3, 1, "신사임당", 85), new StudentDTO(4, 2, "장보고", 95), new StudentDTO(5, 2, "선덕여왕", 75));

StudentDTO student = stream4.reduce((a, b) -> (a.getScore() > b.getScore()) ? a : b).get();
System.out.println("가장 스코어가 높은 학생 : " + student);

.>가장 스코어가 높은 학생 : StudentDTO [no=4, classNo=2, name=장보고, score=95]

 

가장 높은 점수를 가진 학생을 찾기 위해 reduce() 메서드를 사용합니다.

 

reduce() 메서드는 스트림의 요소를 반복적으로 결합하여 하나의 결과를 도출합니다. 이때 첫 번째 인수로 전달된 람다식은 BinaryOperator<T> 타입의 함수형 인터페이스로, 스트림의 요소를 결합하는 방법을 정의합니다.

 

따라서 해당 코드에서는 reduce() 메서드를 호출하여, 스트림의 요소인 StudentDTO 객체들 중에서 가장 높은 점수를 가진 객체를 반환합니다. 이때 람다식은 a와 b를 비교하여, a의 점수가 b의 점수보다 높으면 a를, 그렇지 않으면 b를 반환합니다.

 

reduce() 메서드의 반환값은 Optional<T> 타입으로, 스트림이 비어있을 수 있기 때문에 Optional 클래스를 사용하여 null-safe하게 값을 처리합니다. 따라서 get() 메서드를 사용하여 Optional<StudentDTO> 타입에서 StudentDTO 객체를 추출하고, 이를 출력합니다.

즉, 해당 코드는 stream4 스트림의 요소 중에서 가장 높은 점수를 가진 학생을 출력하는 코드입니다.

SMALL

'java' 카테고리의 다른 글

람다(lambda)식 API  (0) 2023.04.06
람다(lambda)식 사용해보기  (0) 2023.04.05
ENUM 열거형이란?  (0) 2023.04.05
java Exception13  (1) 2023.01.09
java Collection12-Set,Linked,Map  (0) 2023.01.09

+ Recent posts