ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 스트림(Stream)
    JAVA 2023. 3. 16. 13:23

    • 물이 흐르듯이 객체를 연속척으로 처리하는 기능
    • 요소들이 하나씩 흘러가면서 처리된다는 의미
    • 람다식을 이용

     

    스트림의 특징

    1. 처리 속도가 빠르고, 병렬 처리에 효율적(= 내부 반복자의 특징)
    2. 람다식으로 다양한 요소 처리 정의 가능
    3. 중간 처리와 최종 처리를 수행하도록 파이프 라인 형성 가능

     


    내부 반복자

    • 내부 반복자 : 요소 처리 방식을 컬렉션 내부로 주입시켜 내부에서 요소를 반복 처리
    • 외부 반복자 : 컬렉션의 요소를 컬렉션에서 반복적으로 꺼내와서 처리
    • 스트림을 이용하면 병령 처리가 가능하며, 이로 인해 CPU 처리 효율성 증대를 꾀할 수 있다.
      - 처리하는 요소가 적을 때는 멀티 스레드보다 싱글 스레드가 더 효율적이다.
      - 멀티 스레드 등의 병렬 처리는 처리하는 요소가 많을 경우에 더 효율적이다.

     


    중간 처리와 최종 처리

    • 스트림을 여러 개 연결해서 사용할 수도 있다.
    • 중간 스트림 : 최종 처리할 요소를 걸러내거나(필터링) 변환(매핑), 정렬하는 등의 작업을 수행
    • 최종 처리 : 중간 처리를 통해 정제된 요소를 반복, 집계(카운팅, 총합 평균 등) 작업을 수행

     

    데이터(컬렉션, 배열) 중간 처리 최종 처리 결과
    오리지널 스트림 중간 스트림1 중간 스트림2 집계 처리  
    한국인 남자 군필자 남은 사람 수를 집계 한국인 중 군 제대한 남자의 수
    Student(학생 객체) score(점수 필드)   평균 계산 학생들의 평균 점수

     

    //Student 스트림 - 오리지널 스트림
    Stream<Student> studentStream = list.stream();
     
    //score 스트림 - 중간 스트림
    IntStream scoreStream = studentStream.mapToInt( student -> student.getScore() );    //Student 객체를 getScore() 메소드의 리턴 값으로 매핑 
     
    //평균 계산 - 최종 처리
    double avg = scoreStream.average().getAsDouble();

     

    • 대부분의 map으로 시작하는 메소드는 어떤 객체의 타입을 바꾸는 메소드이다.
      - 위의 예제에서 평균 점수를 계산하기 위해 mapToInt() 메소드를 이용해 Student 객체를 int 타입의 score 값으로 매핑했다.

     


    리소스로부터 스트림 얻기

     

    스트림 인터페이스의 종류

    패키지 부모 인터페이스 자식 인터페이스 데이터 타입
    java.util.Stream BaseStrem Stream 참조 타입(객체)
    IntStream int 타입
    LongStream long 타입
    DoubleStream double 타입(실수)

     

    스트림 구현 객체를 얻는 메소드

    클래스/인터페이스 메소드 대상 리소스 비고
    Collection(java.util) static Stream<T> stream() List 컬렉션  
    static Stream<T> parallelStream() Set 컬렉션 병렬 스트림
    Arrays static Stream<T> stream(T[ ]) 배열  
    static IntStream stream(int[ ]) 배열  
    static LongStream stream(long[ ]) 배열  
    static DoubleStream stream(double[ ]) 배열  
    Stream static Stream<T> of(T[ ]) 배열  
    IntStream static IntStream of(int[ ]) 배열  
    static IntStream range(int, int) 숫자 범위 마지막 숫자 미포함
    static IntStream rangeClosed(int, int) 숫자 범위 마지막 숫자 포함
    LongStream static LongStream of(long[ ]) 배열  
    static LongStream range(long, long) 숫자 범위 마지막 숫자 미포함
    static LongStream rangeClosed(long, long) 숫자 범위 마지막 숫자 포함
    DoubleStream static DoubleStream of(double[ ]) 배열  
    Files static Stream<Path> list(Path) 디렉토리  
    static Stream<String> lines(Path, Charset) 텍스트 파일  
    Random static IntStream ints(...) 난수  
    static LongStream longs(...) 난수  
    static DoubleStream doubles(...) 난수  

     


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

    • java.util.Collection 인터페이스의 stream()과 parallelStream() 메소드 사용
      - parallelStream() 메소드는 병렬 처리 시 사용

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    public class Product {
        private int pno;
        private String name;
        private String company;
        private int price;
        
        public Product(int pno, String name, String company, int price) {
            this.pno = pno;
            this.name = name;
            this.company = company;
            this.price = price;
        }
     
        public int getPno() { return pno; }
        public String getName() { return name; }
        public String getCompany() { return company; }
        public int getPrice() {    return price; }
     
        @Override
        public String toString() {
            return new StringBuilder()
                    .append("{")
                    .append("pno:" + pno + ", ")
                    .append("name:" + name + ", ")
                    .append("company:" + company + ", ")
                    .append("price:" + price)
                    .append("}")
                    .toString();
        }
    }

     

    //List 컬렉션 생성
    List<Product> list = new ArrayList<>();
     
    for(int i=1; i<=5; i++) {
        Product product = new Product(1"상품"+i, "멋진 회사", (int)(10000*Math.random()));
        list.add(product);
    }
     
    //객체 스트림 얻기
    Stream<Product> stream = list.stream();
    stream.forEach(p -> System.out.println(p));

     

    실행 결과

     


    배열로부터 스트림 얻기

    • java.util.Arrrays 클래스의 stream() 메소드 사용

     

    //참조 타입(객체) 배열
    String[] strArray = {"홍길동""김길동""남길동"};
    Stream<String> strStream = Arrays.stream(strArray);
    strStream.forEach(item -> System.out.print(item + ","));
    System.out.println();
     
    //기본 타입(int, long, double) 배열
    int[] intArray = { 12345 };
    IntStream intStream = Arrays.stream(intArray);
    intStream.forEach(item -> System.out.print(item + ","));
    System.out.println();

     

    실행 결과

     


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

    • IntStream, LongStream의 range()와 rangeClosed() 메소드 사용

     

    public static int sum;
     
    public static void main(String[] args) {
        IntStream stream = IntStream.range(1100);    //1부터 100미만의 정수 스트림 생성
        stream.forEach(a -> sum += a);    //1부터 100까지 합산
        System.out.println("총합:" + sum);
    }

     

    실행 결과

     


    파일로부터 스트림 얻기

    • java.nio.file.Files의 lines() 메소드 사용하여 텍스트 파일의 행 단위 스트림을 얻을 수 있다.
      - 파일 경로(Path)와 인코딩할 문자셋(Charset) 필요

     

    data.txt
    0.00MB

     

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    //해당 소스 파일과 동일한 디럭토리(패키지) 내부의 data.txt 파일 내용을 콘솔에 출력하는 프로그램
    try {
        Path path = Paths.get(StreamExample.class.getResource("data.txt").toURI());    //data.txt 파일의 경로의 Path 객체 생성
        Stream<String> stream = Files.lines(path, Charset.defaultCharset());    // 해당 경로의 파일 내용을 기본 문자셋으로 인코딩하여 스트림 생성 
        stream.forEach(line -> System.out.println(line));
        stream.close();
        
    catch (URISyntaxException e) {
        e.printStackTrace();
    catch (IOException e) {
        e.printStackTrace();

     

    실행 결과

     


    URI와 URL

    • URI(Uniform Resource Identifier) : 특정 리소스를 식별하는 통합 자원 식별자
      - 웹 기술에서 사용하는 논리적/물리적 리소스를 식별하는 고유의 문자열 시퀀스
    • URL(Uniform Resource Locator) : 특정 리소스의 위치를 가리키는 문자열
      - 컴퓨터 네트워크 상에서 리소스가 어디 있는지 알려주기 위한 규약
      - URI의 서브셋
      - 리소스의 위치 정보도 고유한 값이기 때문에 URL을 URI로 변환해주는 메소드가 존재한다.(URI toURI())f

     


    'JAVA' 카테고리의 다른 글

    데이터 입출력  (0) 2023.03.17
    스트림 요소 처리  (0) 2023.03.16
    StringTokenizer를 이용한 문자열 파라미터 변환  (0) 2023.03.15
    람다식(Lamda Expression)  (0) 2023.03.15
    문자열 관련 클래스  (0) 2023.03.14
Designed by Tistory.