JAVA - 람다와 스트림(4)

DevSeoRex·2022년 11월 4일
0
post-thumbnail

스트림(Stream)

  • 데이터 소스를 추상화 하고, 데이터를 다루는데 자주 사용되는 메서드들을 정의 해놓음
  • 데이터 소스가 무엇이던 간에 같은 방식으로 다룰 수 있게 되었음
  • 코드의 재사용성이 높아짐
  • 스트림을 이용하면, 배열이나 컬렉션뿐만 아니라 파일에 저장된 데이터도 모두 같은 방식으로 다룰 수 있음

스트림 생성

아래와 같은 리스트가 있다고 할때, 두 데이터 소스를 기반으로 하는 스트림은 다음과 같이 생성할 수 있다.

// 문자열 배열과 같은 내용의 문자열을 저장하는 List를 선언
String[] strArr = { "aaa", "bbb", "ccc" };
List<String> strList = Arrays.asList(strArr);

// 두 데이터 소스를 기반으로 하는 스트림을 생성

// 스트림을 생성
Stream<String> strStream1 = strList.stream(); 	

// 스트림을 생성
Stream<String> strStream2 = Arrays.stream(strArr); 

이 두 스트림의 데이터 소스의 데이터를 읽어서 정렬하고 화면에 출력하려면 아래와 같다.
데이터 소스(원본)가 정렬되는 것은 아니라는 것에 유의해야 한다.

// Stream을 사용하지 않았을때
Arrays.sort(strArr);
Collections.sort(strList);

for(string str : strArr)
	System.out.println(str);
    
for(String str : strList)
	System.out.println(str);

// Stream을 사용하고 정렬하여 출력
strStream1.sorted().forEach(System.out::println);
strStream2.sorted().forEach(System.out::println);

스트림의 특징

  • 스트림은 데이터 소스를 변경하지 않는다.
    - 스트림은 데이터 소스로 부터 데이터를 읽고, 데이터 소스를 변경하지는 않는다.
    • 아래와 같은 방법으로 정렬된 결과를 컬렉션이나 배열에 담아서 반환할 수도 있다.
// 정렬된 결과를 새로운 List에 담아서 반환한다.
List<String> sortedList = strStream2.sorted().collect(Collectors.toList());
  • 스트림은 일회용이다.
    - 스트림은 Iterator처럼 일회용이다.
    • Iterator로 컬렉션의 모든 요소를 순회하고 나면 다시 사용할 수 없다.
    • 스트림은 한번 사용하면 닫혀서 사용할 수 없으므로, 필요하다면 다시 생성해야 한다.
strStraem1.sorted().forEach(System.out::println);
int numOfStr = strStream1.count(); // 에러. 스트림이 이미 닫혔음
  • 스트림은 작업을 내부 반복으로 처리한다.
    - 내부 반복이란 반복문을 메서드의 내부에 숨길 수 있다는 것을 의미한다.
    • forEach( )는 스트림에 정의된 메서드 중의 하나인데, 매개변수에 대입된 람다식을 데이터 소스의 모든 요소에 적용한다.

forEach( )는 메서드 안으로 for문을 넣은 것이다.

스트림의 연산

스트림에 정의된 메서드 중에서 데이터 소스를 다루는 작업을 수행하는 것을 연산이라고 한다.
스트림이 제공하는 연산은 중간 연산과 최종 연산으로 분류할 수 있다.

중간 연산은 연산결과를 스트림으로 반환하기 때문에 중간 연산을 연속해서 연결할 수 있다.
최종 연산은 스트림의 요소를 소모하면서 연산을 수행하므로 단 한번만 연산이 가능하다.

모든 중간 연산의 결과는 스트림이다.
다만 연산전의 스트림과 같은 것은 아니다.

Stream의 연산 예제코드

String[] strArr = { "dd", "aaa", "CC", "cc", "b" };
Stream<String> stream = Stream.of(strArr); 					// 문자열 배열이 소스인 스트림
Stream<String> filteredStream = stream.filter(); 			// 걸러내기(중간 연산)
Stream<String> distinctedStream = stream.distinct(); 		// 중복제거(중간 연산)
Stream<String> sortedStream = stream.sort(); 				// 정렬(중간 연산)
Stream<String> limitedStream = stream.limit(5); 			// 스트림 자르기(중간 연산)
int total = stream.count(); 								// 요소 개수 세기(최종 연산)

출처 : 자바의 정석 3rd(남궁성 저 , 도우출판)

0개의 댓글