ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • stream(스트림) 개념, 예제
    Java/Java 문법 종합반 강의 정리 2024. 1. 9. 12:52

    스트림은 Java8 부터 제공되는, 한번 더 추상화된 자료구조와 자주 사용하는 프로그래밍 API를 제공한 것이다.

    자료구조를 한번 더 추상화 했기 때문에, 자료구조의 종류에 상관 없이 같은 방식으로 다룰 수 있다.

    ( + 병렬 처리에 유리한 구조로 조건부로 성능도 챙길 수 있다.)

     

    조금 더 쉽게 비유하자면, 자료구조의 "흐름"을 객체로 제공해주고, 그 흐름동안 사용할 수 있는 메서드들을

    api로 제공해 주는 것이다.

     


     

    스트림의 특징

    1. 원본의 데이터를 변경하지 않는다.

     - 자바 컬렉션으로부터 스트림(해당 컬렉션의 흐름)을 받아서 한 번 사용한다.

    2. 일회용이다.

     - 한 번 사용한 스트림은 어디에도 남지 않는다.

    위는 java.collection 내부의 stream() 메서드 이다.

    모든 컬렉션을 상속하는 구현체들은 스트림을 반환 할 수 있다.

     

    스트림과 거기에 구현되어 있는 메서드들을 사용하면 다음과 같은 것들이 가능하다. (이전 글의 예제 참고)

    List<Car> benzParkingLot =
    	// carsWantToPark의 스트림값을 받아와서
        carsWantToPark.stream()
    	// 거기 구현되어 있는 filter()메서드를 사용합니다.
    	// filter메서드는 함수를 파라미터로 전달받습니다.
    	// 여기서 함수는 제조사가 벤츠면 true를 반환하는 함수네요.
    	// 필터 메서드는 이름처럼 false를 반환한 스트림의 원소들을 제거합니다.
                .filter((Car car) -> car.getCompany().equals("Benz"))
    			// 이 결과도 반환을 받아서 다시 리스트로 묶어줍니다.
                .toList();

    위의 로직을 정리해보면

    1. 스트림 객체를 받는다.

    2. 해당 객체는 자료구조의 모든 원소가 있다.

    3. filter()와 같은 이미 구현된 메소드도 있다.

    4. filter() 메서드는 true/false 값을 return하는 함수를 파라미터로 전달받는다.

    5. filter() 메서드는 스트림에 들어있는 모든 원소에 파라미터로 전달받은 함수를 실행시켜보면서

     false가 나온 원소를 제거한 스트림을 반환해준다.

     (위 코드의 경우 모든 원소가 익명함수의 Car car 파라미터로 자동으로 전달된다.)

    6. 해당 결과를 다시 컬렉션으로 묶어주는 메서드도 정의되어있다.

     

    간단하게 생각하면 다음과 같은 일을 하고 있는 것이다.

    ArrayList<Car> benzParkingLotWithoutStream = new ArrayList<>();
    
    for (Car car : carsWantToPark) {
        if (car.getCompany().equals("Benz")) {
            benzParkingLotWithoutStream.add(car);
        }
    }

     


     

    스트림을 사용하는 방법

    1. 스트림을 받아오기 (.stream())

    carsWantToPark.stream()

    2. 스트림 가공하기

    .filter((Car car) -> car.getCompany().equals("Benz"))

     

    3. 스트림 결과 만들기

    .toList();

     


     

    스트림 API

    스트림 api는 너무 방대해서 한번에 다 소개할수도, 배울수도 없다.

    코드를 마주 할 때 마다, 혹은 사용해보면서 어떤 것들이 있는지 알아보는것이 중요하다.

     

    그래도 가장 대표적인 api인 map(), forEach(), filter() 정도는 가장 자주 사용되기 때문에 꼭 확인하고 넘어가자.

     

    forEach()

    List<String> carNames = Arrays.asList("Series 6", "A9", "Ionic 6");
    
    carNames.stream()
        .forEach(System.out::println);
    
    // 결과 
    // Series 6
    // A9
    // Ionic 6

    - 각각의 원소에 넘겨받은 함수를 실행해준다.

    - 하지만 넘겨받은 반환값을 가지고 뭘 하지는 않으며, 있다고 해도 무시된다.

     

    map()

    carNames.stream()
    	.map(name -> name.toUpperCase()).toList();
    
    // 결과
    // ["SERIES 6", "A9", "IONIC 6"]

    - forEach와는 반대로 넘겨받은 토대로 값을 변환시키는데 주로 사용된다.

     

    나머지 스트림 api들도 정말 유용한 것들이 많다. 다만 지금은 map, filter, foreach 정도와 결과를 가져오는 몇가지 코드만

    이해하고 넘어가는 것이 좋을 것 같다.

    아래의 링크에서 다양한 stream Api들을 확인 할 수 있다.

    https://www.baeldung.com/java-8-streams

     

     

Designed by Tistory.