1. 스트림(stream)이란?

  • '데이터의 흐름'입니다.
  • 컬렉션의 저장 요소를 하나씩 참조해서 람다식으로 처리할 수 있도록 해주는 반복자입니다.
  • 스트림을 활용해서 필터링, 데이터 변경, 다른 타입이나 자료구조로 변환 등을 할 수 있습니다.

 

2. 스트림의 특징

  • 데이터 소스를 변경하지 않습니다.
  • 작업을 내부적으로 반복 처리합니다. (하나씩 꺼내 쓴다)
  • 컬렉션의 요소를 모두 읽고 나면 닫혀서 재사용이 불가능합니다. 그러므로 필요할 경우 재생성을 해야 합니다.

 

3. 스트림의 구조

  3-1) 스트림 생성

  • 스트림을 이용하기 위해 먼저 스트림을 생성해야합니다.
  • Stream<T> Collection.stream() 을 이용하여 해당하는 컬렉션을 기반으로하는 스트림을 생성할 수있습니다.

 

  3-2) 중간 연산

  • 중간 단계로써 데이터의 형변환 혹은 필터링, 정렬 등 스트림에 대한 가공을 해줍니다.
  • map(변환) / sorted(정렬) / skip(스트림 자르기) / limit(스트림 자르기) 등이 있습니다.

 

  3-3) 최종 연산

  • 스트림의 요소를 소모해서 결과를 반환하는 단계입니다. 최종 연산 이후에는 스트림이 닫히게 되고 더 이상 사용할 수 없습니다.
  • 최종 연산의 결과값은 단일 값일 수도 있으며 배열 혹은 컬렉션일 수도 있습니다.
  • collect()를 이용해서 다른 콜렉션으로 바꾸는 것, reduce를 이용해서 incremental calculation하는 것도 가장 많이 쓰이는 패턴입니다.

 

4. 스트림 예제

import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

public class Main {
    public static void main(String[] args) {
        List<String> list = new ArrayList<>();
        list.add("서울");
        list.add("부산");
        list.add("속초");
        list.add("서울");

        System.out.println(list); // [서울, 부산, 대구, 서울]
        List<String> result = list.stream() // 스트림 생성
                                  .limit(2) //중간 연산 //2개만
                                  .collect(Collectors.toList()); // 최종 연산 // List로 만들거다
        System.out.println(result);

        System.out.println("list -> transformation -> set");
        Set<String> set = list.stream()
                              .filter("서울"::equals)
                              .collect(Collectors.toSet()); //set으로 만들거다
        set.forEach(System.out::println); // 서울  // set은 중복데이터가 허용되지 않으므로
    }
}

 

 

5. 스트림 예제 2: Array를 Stream으로 변환

public class Main {
    public static void main(String[] args) {
        String[] arr = {"엑셀보다 쉬운 SQL", "웹개발 종합반",
                "알고보면 알기쉬운 알고리즘", "웹개발의 봄,Spring"};
        Stream<String> stringStream = Arrays.stream(arr);
        stringStream.forEach(className -> System.out.println("수업명 : " + className));
        //stringStream.forEach(System.out::println); // 람다 약식
        System.out.println();
    }
}

 

6. 스트림 예제 3: map연산 활용

6-1) build.gradle의 dependencies 코드 블럭에 library를 추가

dependencies {
	implementation 'org.apache.commons:commons-lang3:3.0'
  // other codes..
}

 6-2) 예제 코드

import org.apache.commons.lang3.tuple.Pair;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

class Sale {
    String fruitName;
    int price;
    float discount;

    public Sale(String fruitName, int price, float discount) {
        this.fruitName = fruitName;
        this.price = price;
        this.discount = discount;
    }
}

public class Main {
    public static void main(String[] args) {
        List<Sale> saleList = Arrays.asList(
                new Sale("Apple", 5000, 0.05f),
                new Sale("Grape", 3000, 0.1f),
                new Sale("Orange", 4000, 0.2f),
                new Sale("Tangerine", 2000, 0)
        );

        Stream<Sale> saleStream = saleList.stream();
        saleStream
                .map(sale -> Pair.of(sale.fruitName, sale.price * (1 - sale.discount)))
                .forEach(pair -> System.out.println(pair.getLeft() + " 실 구매가:  " + pair.getRight() + "원 "));
    }
}

 

7. 스트림 예제 4: reduce를 이용한 계산

 

public class Main {
    public static void main(String[] args) {
        List<Integer> numArr = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        Integer result = numArr.stream().reduce(0, Integer::sum);
        //reduce와 sum을 활용하여 1부터 10까지 더하게 됩니다.
        System.out.println(result);
    }
}

+ Recent posts