Java / / 2022. 8. 31. 14:27

[Java] 자바 Stream (map, filter, sorted, collect)

반응형

▶ Stream 이란?

스트림의 사전적 의미는 '흐르다' 또는 '개울'이다.

프로그래밍에서의 스트림도 사전적 의미와 크게 다르지 않다.

다만, 여기서 물이 흐르는 것은 아니고 데이터의 흐름을 뜻한다고 이해하면 될 것이다.

 

Java 8부터 Stream을 사용할 수 있다.

기존에 자바 컬렉션이나 배열의 원소를 가공할 때, for문 / foreach 등으로 원소 하나씩 골라내어 가공을 했지만, stream을 이용하여 람다 함수로 간결하고 깔끔하게 요소들을 처리 가능하게 되었다.

 

 

※ 간략 정리

  • 데이터의 흐름이다.
  • Java 8에서 추가한 람다를 활용할 수 있는 기술 중 하나이다.
  • 배열 / 컬렉션 인스턴스에 함수 여러 개를 조합해서 원하는 결과를 필터링하고 가공된 결과를 얻는다.
  • 한 번 종료 작업을 한 스트림에 대해서는 재사용 불가능 한다.
  • 병렬 처리 가능 => 여러 개의 스레드가 작업한다.

 

참고 : 이해하기 쉬운 그림과 설명이 있어서 참고하면 좋을 것 같다.

출처 : https://steady-coding.tistory.com/309

어부가 물고기를 그물로 잡고, 여러 마리를 일정한 기준으로 모아서 상자에 넣는다. 이들을 하나로 모은 뒤 트럭에 실어서 우리가 소비하는 단계까지의 과정을 나타내는 그림이다.

 

stream도 이와 비슷하다고 보면 된다. 물고기와 같은 어류의 이동을 stream이라고 정의할 수 있다.

 

  1. 어부가 어류 중에서도 고등어를 잡고 싶어 그물로 고등어를 잡았다고 하자. 이 행위를 filter라고 하며, 중간 연산자라고 한다.
  2. 고등어를 포장하지 않고 생으로 팔 수는 없기 때문에 상자에 담아야 한다. 이 행위를 map이라고 하고, 마찬가지로 중간 연산자라고 한다.
  3. 고등어가 실린 수많은 상자를 운반하여 다른 곳으로 이동하면 끝이 난다. 이 행위를 collect라고 하고, 최종 연산자라고 한다.

이와 같이 스트림은 수많은 데이터의 흐름 속에서 각각의 원하는 값을 가공하여 최종 소비자에게 제공하는 역할을 한다고 보면 된다.

 

 

※ 간략 정리

  • 생성하기 : 스트림 인스턴스 생성
  • 가공하기 : filtering, mapping 등 원하는 결과를 만들기
  • 결과 만들기 : 최종 결과를 만들어내는 작업
객체.스트림생성().가공().결과만들기(); //파이프라인이라고 부른다고도 한다.

 


 

 

▶ Stream의 특징

기능적인 측면에서 스트림은 컬렉션(배열 포함)의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자이다.

 

1️⃣ 람다식으로 요소 처리 코드를 제공한다.

스트림은 람다식 또는 메서드 참조를 이용한다. 따라서 코드 간결해지는 장점이 있다.

 

2️⃣ 내부 반복자를 사용하므로 병렬 처리가 쉽다.

외부 반복자란 개발자가 코드로 직접 컬렉션의 요소를 반복해서 가져오는 코드 패턴을 뜻한다.

우리가 흔히 사용하는 index를 이용한 반복문이나, Iterator를 사용한 while문은 모두 외부 반복자를 이용해야 하는 것이다.

반면, 내부 반복자는 컬렉션 내부에서 요소들을 반복시키고, 개발자는 요소당 처리해야 할 코드만 제공하는 코드 패턴을 말한다.

출처 : https://steady-coding.tistory.com/309

 

스트림은 람다식으로 요서 처리 내용만 전달할 뿐, 반복은 컬렉션 내부에서 일어난다. 

따라서 요소의 병렬 처리가 컬렉션 내부에서 처리되므로 효율적인 병렬 처리가 가능하다.

 

3️⃣ 중간 처리와 최종 처리가 존재한다.

스트림은 컬렉션 요서에 대해 중간 처리와 최종 처리를 수행할 수 있다.

중간 처리에서는 mapping, filtering, sorting을 수행하고, 최종 처리에서는 반복, 평균, 총합 등의 집계 처리를 수행한다.

 

 


 

▶ Stream 중간 연산자 예시

 

ArrayList<string> list = new ArrayList<>(Arrays.asList("Apple","Banana","Melon","Grape","Strawberry"));

System.out.println(list);

//[Apple, Banana, Melon, Grape, Strawberry]

💡 map

list.stream().map(s->s.toUpperCase());
list.stream().map(String::toUpperCase);

 

  • 리스트의 요소들을 대문자로 변경한다.

 

요소들을 대문자로 가공하고,  collect를 이용하여 결과를 리턴 받은 뒤, forEach를 이용하여 바로 출력해 볼 수 있다.

System.out.println(list.stream().map(s->s.toUpperCase()).collect(Collectors.joining(" ")));
//APPLE BANANA MELON GRAPE STRAWBERRY

System.out.println(list.stream().map(s->s.toUpperCase()).collect(Collectors.toList()));
//[APPLE, BANANA, MELON, GRAPE, STRAWBERRY]
System.out.println(list.stream().map(String::toUpperCase).collect(Collectors.toList()));
//[APPLE, BANANA, MELON, GRAPE, STRAWBERRY]

list.stream().map(String::toUpperCase).forEach(s -> System.out.println(s));
//APPLE
//BANANA
//MELON
//GRAPE
//STRAWBERRY
  • Collectors.joining을 이용해 리스트를 조인의 기준으로 배치할 수 있습니다. String으로 리턴합니다.
  • Collectors.toList를 이용해 리스트로 리턴 받을 수 있습니다.
  • forEach 요소마다 각각 작업을 할 수 있습니다.

💡 filter

list.stream().filter(t->t.length()>5)
  • filter는 요소를 특정 기준으로 걸러낼 수 있습니다.

 

요소의 크기가 5 이상인 값만 뽑아냅니다.

System.out.println(list.stream().filter(t->t.length()>5).collect(Collectors.joining(" ")));
//Banana Strawberry

System.out.println(list.stream().filter(t->t.length()>5).collect(Collectors.toList()));
//[Banana, Strawberry]

마찬가지로 filter로 가공한 결과를 얻을 수 있습니다.


💡 sorted

list.stream().sorted()
  • 리스트의 요소를 정렬합니다.

 

System.out.println(list.stream().sorted().collect(Collectors.toList()));
//[Apple, Banana, Grape, Melon, Strawberry]

 


▶ Stream 최종 연산자 예시

💡 collect

  • Collector 타입의 인자를 받아서 처리한다.
  • 예제 외에도 Collectors를 활용한 예는 많지만 생략한다.
productList.stream()
    .map(Product::getName)
    .collect(Collectors.toList()); // 리스트로 결과 가져오기
    
productList.stream()
  .map(Product::getName)
  .collect(Collectors.joining()); // 스트림 작업 결과를 하나의 String으로 이어붙이기
  
productList.stream()
  .map(Product::getName)
  .collect(Collectors.joining(", ", "<", ">")); //<요소1, 요소2, 요소3>
  
productList.stream()
  .collect(Collectors.averagingInt(Product::getAmount)); // 숫자 값의 평균

 


 

▶ 참고

https://steady-coding.tistory.com/309

https://dpdpwl.tistory.com/81

 

[Java]자바 스트림Stream(map,filter,sorted / collect,foreach)

자바8부터 Stream 을 사용 할 수 있습니다. 기존에 자바 컬렉션이나 배열의 원소를 가공할떄, for문, foreach 등으로 원소 하나씩 골라내여 가공을 하였다면, Stream 을 이용하여 람다함수형식으로 간결

dpdpwl.tistory.com

 

Stream이란? - 기본 개념과 특징 (JAVA)

안녕하세요? 코딩중독입니다. 저번 시간에는 주요 함수적 인터페이스를 알아 보았는데, 오늘부터는 람다가 아닌 스트림에 대한 이야기를 하려고 합니다. Stream이란? 스트림의 사전적 의미는 '흐

steady-coding.tistory.com

 

반응형
  • 네이버 블로그 공유
  • 네이버 밴드 공유
  • 페이스북 공유
  • 카카오스토리 공유