본문 바로가기

Language/Java

Java 스트림 (Stream) 사용법 및 정리 1/3 (Map, Filter, FlatMap ..)

반응형

목차

· Stream이란?

· Stream Pipeline

· Filter

· Map

· Sorted

· Distinct

· FlatMap


Stream이란?


  • 스트림은 '데이터의 흐름'이다.
  • 자바 8부터 추가되어 컬렉션(Collection) 형태로 구성된 데이터를 람다를 이용해 간결하고 직관적으로 처리할 수 있게 해 준다.
  • For, while 등을 이용하던 기존 loop를 대체할 수 있다.
  • 쉽게 병렬 처리를 할 수 있게 해 준다.

다음 예시는 문자열 데이터를 가진 Stream을 생성하고 List로 변환했다. 

Stream<String> nameStream = Stream.of("Kim", "An", "Oh");
List<String> names = nameStream.collect(Collectors.toList());

 

Stream Pipeline(구조)


스트림 파이프라인은 크게 세 가지로 구성되어 있다. 

컬렉션으로 들어온 데이터들이 여러 개의 중간 처리 과정을 거쳐 종결처리된다. 

자세한 예시는 뒤에서 확인할 수 있다.

 

Source (소스)

컬렉션, 배열 등

 

Intermediate Operations (중간 처리)

0개 이상의 filter, map 등의 중간처리

 

Terminal Operation (종결 처리)

Collect, reduce 등

 

아래에서는 중간 처리에서 사용되는 여러 스트림 함수를 확인할 수 있다.

 

Filter


특정 조건을 만족하는 데이터만 걸러내는 데 사용한다.

Predicate에 true를 반환하는 데이터만 존재하는 stream을 리턴한다.

Stream<T> filter(Predicate<? super T> predicate);

다음 예시는 Filter를 사용해 나이가 30 이상인 회원을 조회하는 기능이다. 2명만 필터링된 것을 확인할 수 있다.

ist<Member> members = new ArrayList<>();
members.add(new Member("Kim", 20, false));
members.add(new Member("An", 40, true));
members.add(new Member("Oh", 60, false));

List<Member> ageFilteredList = members.stream()
        .filter(x -> x.getAge() > 30)
        .collect(Collectors.toList());
System.out.println("ageFilteredList = " + ageFilteredList);

// ageFilteredList = [Member{name='An', age=40, isVerified=true}, Member{name='Oh', age=60, isVerified=false}]

Map


데이터를 변형하는 데 사용한다.

데이터에 해당 함수가 적용된 결과물을 제공하는 stream을 리턴한다.

<R> Stream<R> map(Function<? super T, ? extends R> mapper);

 

다음 예시는 Map을 사용해 Member 리스트를 나이를 가진 Integer 리스트로 변형하는 코드이다.

 List<Integer> ageList = members.stream()
        .map(x -> x.getAge())
        .collect(Collectors.toList());
System.out.println("ageList = " + ageList);

//ageList = [20, 40, 60]

Sorted


데이터가 순서대로 정렬된 stream을 리턴한다.

데이터의 종류에 따라 Comparator가 필요할 수 있다.

Stream<T> sorted();
Stream<T> sorted(Comparator<? super T> comparator);

 

다음 예시는 Member 리스트를 Sorted를 사용해 이름 기준으로 알파벳 오름차순 정렬한 이후에 이름만 추출했다.

List<Member> members = new ArrayList<>();
members.add(new Member("Kim", 20, false));
members.add(new Member("An", 40, true));
members.add(new Member("Oh", 60, false));

List<String> nameAscList = members.stream()
        .sorted((o1, o2) -> o1.getName().compareTo(o2.getName()))
        .map(Member::getName)
        .collect(Collectors.toList());
System.out.println("nameAscList = " + nameAscList);

// nameAscList = [An, Kim, Oh]

 

Distinct


중복되는 데이터가 제거된 stream을 리턴한다.

Stream<T> distinct();

 

다음 예시는 Member 리스트를 Distinct를 사용해 중복을 제거하고, 이름만 추출했다.

List<Member> members = new ArrayList<>();
members.add(new Member("Kim", 20, false));
members.add(new Member("An", 40, true));
Member oh = new Member("Oh", 60, false);
members.add(oh);
members.add(oh);

 List<String> distinctList = members.stream()
    .distinct()
    .map(Member::getName)
    .collect(Collectors.toList());
System.out.println("dis = " + distinctList);

// dis = [Kim, An, Oh]

FlatMap


Map + Flatten

데이터에 함수를 적용한 후 중첩된 stream을 연결하여 하나의 stream으로 리턴한다.

<R> Stream<R> flatMap(Function<? super T, 
	? extends Stream<? extends R>> mapper);

 

다음은 회원 리스트 정보에서 총회원이 가지고 있는 주문 리스트 정보를 가져오는 예시이다.

회원마다 주문 리스트를 가지고 있어 이 주문을 flat 하게 펼치는 작업을 flatMap을 통해 진행한다.

ArrayList<Order> firstOrders = new ArrayList<>();
firstOrders.add(new Order(BigDecimal.valueOf(10)));
firstOrders.add(new Order(BigDecimal.valueOf(20)));

ArrayList<Order> twoOrders = new ArrayList<>();
twoOrders.add(new Order(BigDecimal.valueOf(30)));
twoOrders.add(new Order(BigDecimal.valueOf(40)));

ArrayList<Order> threeOrders = new ArrayList<>();
threeOrders.add(new Order(BigDecimal.valueOf(50)));
threeOrders.add(new Order(BigDecimal.valueOf(60)));

List<Member> members = new ArrayList<>();
members.add(new Member("Kim", 20, false, firstOrders));
members.add(new Member("An", 40, true, twoOrders));
members.add(new Member("Oh", 60, false, threeOrders));


List<Order> collect = members.stream()  // Stream<Member>
    .map(Member::getOrders) // Stream<List<Order>>
    .flatMap(List::stream) // Stream<Order>
    .collect(Collectors.toList());

 

반응형