본문 바로가기

diary/codestates (be39)

05/19-20/22 스트림 Stream 기본 개념

스트림 Stream

배열, 컬렉션의 저장 요소를 하나씩 참조해 람다식으로 이용할 수 있게 해주는 반복자

  • 람다식으로 요소 처리 코드를 제공
  • 내부 반복자 사용 → 병렬 처리
  • 중간 처리와 최종 처리 작업 수행

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

  • Student 클래스
public class Student {
    private String name;
    private int score;

    public Student(String name, int score){
        this.name = name;
        this.score = score;
    }

    public String getName(){
        return name;
    }
    public int getScore(){
        return score;
    }
}
import java.util.*;
import java.util.stream.Stream;

public class LambdaExpressionsExample {
    public static void main(String[] args) {
        //Student 타입의 List를 생성
        List<Student> list = Arrays.asList(
                new Student("jane", 99),
                new Student("john", 88)
        );
		
        //stream()
        //List<Student> 컬렉션으로부터 스트림 객체 생성
        Stream<Student> stream = list.stream();
        
        //stream.forEach() 메서드로 컬렉션의 요소 출력
        stream.forEach( s-> {
            String name = s.getName();
            int score = s.getScore();
            System.out.println(name + "-" + score);
        });
    }
}
출력

jane-99
john-88

2. 내부 반복자를 사용한다 → 병렬 처리가 가능하다

(병렬 처리 스트림 parallelStream()) *보충 필요

 

외부 반복자

개발자가 코드로 직접 컬렉션의 요소를 반복해서 가져오는 코드 패턴 → for, while

내부 반복자

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

병렬 처리: 한 가지 작업을 서브 작업으로 나누고, 서브 작업들을 분리된 스레드에서 병렬적으로 처리하는 것

 

import java.util.*;
import java.util.stream.Stream;

public class ParallelExample {
    public static void main(String[] args) {
        List<String> list = Arrays.asList(
                "치킨", "피자", "떡볶이", "튀김", "순대"
        );

        //순차 처리 스트림 stream()
        Stream<String> stream = list.stream();
        stream.forEach(ParallelExample :: print); //현재 클래스의 print 메서드 참조

        System.out.println();

        //병렬 처리 스트림 parallelStream()
        Stream<String> parallelStream = list.parallelStream();
        parallelStream.forEach(ParallelExample :: print);
    }

    public static void print(String str){
        //매개값으로 입력받은 String과 사용된 Thread의 이름을 출력
        System.out.println(str + " : " + Thread.currentThread().getName());
    }
}
출력

치킨 : main
피자 : main
떡볶이 : main
튀김 : main
순대 : main
//순차 처리 스트림: 하나의 스레드가 요소들을 순차적으로 읽어 합을 구함

떡볶이 : main
튀김 : ForkJoinPool.commonPool-worker-5
순대 : main
피자 : ForkJoinPool.commonPool-worker-19
치킨 : ForkJoinPool.commonPool-worker-23
//병렬 처리 스트림: 여러 개의 스레드가 요소들을 부분적으로 합하고, 부분 합을 최종 결합해 전체 합을 생성​

 

3. 중간 처리와 최종 처리가 가능하다

중간 처리: 매핑, 필터링, 정렬

최종 처리: 반복, 카운팅, 평균, 총합 등의 집계 처리

import java.util.*;

public class MapAndReduceExample {
    public static void main(String[] args) {
        List<Student> studentList = Arrays.asList(
                new Student("mel", 33),
                new Student("yang", 66),
                new Student("alex", 33)
        );

        double avg = studentList.stream()
                //중간 처리(매핑)
                .mapToInt(Student :: getScore)
                //최종 처리(평균)
                .average()
                .getAsDouble();

        System.out.println(avg);
    }
}

→ 중간 처리한 값을 최종 처리에 사용한다


스트림의 종류 - Stream, IntStream, LongStream, DoubleStream

1. 컬렉션으로부터 스트림 얻기

//리스트
List<String> list = Arrays,asList(...);
//스트림 생성
Stream<String> stream = list.stream();

2. 배열로부터 스트림 얻기

//배열
String[] arr = {...};
//스트림 생성
Stream<String> stream = Arrays.stream(arr);

3. 숫자 범위로부터 스트림 얻기

//1~100의 수를 스트림으로 생성
//rangeClosed() 메서드 사용
IntStream stream = IntStream.rangeClosed(1, 100);

4. 파일/디렉터리로부터 스트림 얻기 →→→ 보충