ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • Stream(스트림) - 2. 스트림 생성하기
    Java 2020. 2. 13. 16:26
    반응형

    스트림 생성하기

     스트림의 소스가 될 수 있는 대상은 배열, 컬렉션, 임의의 수 등 다양함

    컬렉션으로 스트림 생성하기

     컬렉션의 최고 조상인 Collection에 stream()이 정의되어 있음

     Collection의 자손인 List와 Set을 구현한 클래스들은 모두 위 메서드로 스트림을 생성할 수 있음

     stream()은 해당 컬렉션을 source(소스)로 하는 스트림을 반환

    Stream<T> Collection.stream()

    예시) List로부터 스트림을 생성하는 코드

    List<Integer> list = Arrays.asList(1,2,3,4,5); // 가변인자
    Stream<Integer> intStream = list.stream();     // list를 소스로 하는 컬렉션 생성

    forEach()

     지정한 작업을 스트림의 모든 요소에 대해 수행

    intStream.forEach(System.out::println); // 스트림의 모든 요소를 출력
    intStream.forEach(System.out::println); // 에러, 스트림이 이미 닫힘

     forEach()의 경우 스트림의 요소를 소모하면서 작업을 수행하므로 같은 스트림에 forEach()를 두 번 호출할 수는 없음

     스트림의 요소를 다시 출력하려면 스트림을 새로 생성해야 함

     forEach()에 의해 스트림의 요소가 소모되는 것이고, 소스의 요소가 소모되는 것이 아니므로 같은 소스로부터 다시 스트림을 생성할 수 있음

    배열로 스트림 생성하기

     배열을 소스로 하는 스트림을 생성하는 메서드는 다음과 같이 Stream과 Arrays에 static 메서드로 정의되어 있음

    Stream<T> Stream.of(T... values) // 가변 인자
    Stream<T> Stream.of(T[])
    Stream<T> Arrays.stream(T[])
    Stream<T> Arrays.stream(T[] array, int startInclusive, int endExclusive)

     문자열 스트림은 다음과 같이 생성함

    Stream<String> strStream = Stream.of("a","b","c"); // 가변 인자
    Stream<String> strStream = Stream.of(new String[]{"a", "b", "c"});
    Stream<String> strStream = Arrays.stream(new String[]{"a", "b", "c"});
    Stream<String> strStream = Arrays.stream(new String[]{"a", "b", "c"}, 0, 3);

    기본형 배열을 소스로 하는 스트림을 생성하는 메서드도 있음

    - IntStream / LongStream / DoubleStream

    예시 : IntStream (사용법은 비슷함)

    IntStream IntStream.of(int... values) // Stream이 아니라 IntStream
    IntStream IntStream.of(int[])
    IntStream Arrays.stream(int[])
    IntStream Arrays.stream(int[] arrays, int startInclusive, int endExclusive)

    특정 범위의 정수로 스트림 생성하기

     IntStream과 LongStream은 지정된 범위의 연속된 정수를 스트림으로 생성해서 반환하는 range()와 rangeClose()를 가지고 있음, 사용 방법은 동일함

    IntStream IntStream.range(int begin, int end)        // end가 범위에 포함안됨
    IntStream IntStream.rangeClosed(int begin, int end)  // end가 범위에 포함됨

    임의의 수로 스트림 생성하기

     난수를 생성하는데 사용하는 Random클래스에는 아래의 인스턴스 메서드들이 포함되어 있음. 해당 메서드는 해당 타입의 난수들로 이루어진 스트림을 반환함

    IntStream    ints()
    LongStream   longs()
    DoubleStream doubles()
    
    /* 생성된 스트림의 난수 범위 */
    Integer.MIN_VALUE <=    ints() <= Integer.MAX_VALUE
       Long.MIN_VALUE <=   longs() <= Long.MAX_VALUE
                  0.0 <= doubles() < 1.0

     해당 메서드들이 반환하는 스트림은 크기가 정해지지 않은 "무한 스트림(infinite stream)"이므로 limit()도 같이 사용하여 스트림의 크기를 제한해주어야 함. limit()은 스트림의 개수를 지정하는데 사용, 무한 스트림을 유한 스트림으로 만들어줌

    IntStream intStream = new Random().list();       // 무한 스트림
    IntStream.limit(5).forEach(System.out::println); // 5개의 요소 출력

     아래의 메서드들은 매개변수로 스트림의 크기를 지정해서 '유한 스트림'을 생성해서 반환하므로 limit()을 사용하지 않아도 됨

    IntStream    ints(long streamSize)
    LongStream   longs(long streamSize)
    DoubleStream doubles(long streamSize)
    
    IntStream intStream = new Random().ints(5); // 크기가 5인 난수 스트림을 반환

     지정된 범위(begin~end)의 난수를 발생하는 스트림을 얻는 메서드 - 단, end는 범위에 포함되지 않음

    IntStream    ints(int begin, int end)
    IntStream    ints(long streamSize, int begin, int end)
    LongStream   longs(long begin, long end)
    LongStream   longs(long streamSize, long begin, long end)
    DoubleStream doubles(double begin, double end)
    DoubleStream doubles(long streamSize, double begin, double end)

    람다식 - iterate(), generate()로 스트림 생성하기

     Stream클래스의 iterate()와 generate()는 람다식을 매개변수로 받아서, 해당 람다식에 의해 계산되는 값들을 요소로 하는 무한 스트림을 생성함

    static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
    static <T> Stream<T> generate(Supplier<T> s)

    iterate()

     씨앗값(seed)으로 지정된 값부터 시작해서, 람다식 f에 의해 계산된 결과를 다시 seed값으로 해서 계산을 반복

    Stream<Integer> eventStream = Stream.iterate(0, n -> n+2); // 0, 2, 4, 6, ...

    generate()

     람다식에 의해 계산되는 값을 요소로 하는 무한 스트림을 생성해서 반환

     iterate()와 달리 이전 결과를 이용해서 다음 요소를 계산하지 않음

    Stream<Double>  randomStream = Stream.generate(Math::random);
    Stream<Integer> oneStream    = Stream.generate(() -> 1);

     정의된 매개변수의 타입은 Supplier<T>이므로 매개변수가 없는 람다식만 허용됨.

    유의할 점

     iterate()와 generate()에 의해 생성된 스트림을 기본형 스트림타입의 참조변수로 다룰 수 없음

    IntStream      evenStream = Stream.iterate(0, n -> n+2);   // 에러
    DoubleStream randomStream = Stream.generate(Math::random); // 에러

     굳이 필요하다면, mapToInt()와 같은 메서드로 변환해야 사용 가능

    IntStream evenStream = Stream.iterate(0, n -> n+2).mapToInt(Integer::valueOf);
    Stream<Integer> stream = evenStream.boxed(); // IntStream -> Stream<Integer>

    파일로 스트림 생성하기

    Path를 요소로하는 스트림

     java.nio.file.Files는 파일을 다루는데 필요한 유용한 메서드들을 제공

     list()는 지정한 디렉터리(dir)에 있는 파일의 목록을 소스로 하는 스트림을 생성해서 반환

    Path는 하나의 파일 또는 경로를 의미함
    Stream<Path> Files.list(Path dir)

     이 외에도 Files 클래스에는 Path 요소로 하는 스트림을 생성하는 메서드들은 더 있음 (필요하면 찾아볼 것)

    파일의 한 행(line)을 요소로 하는 스트림

     파일의 한 행(line)을 요소로 하는 스트림을 생성하는 메서드도 있음

     파일 뿐만 아니라 다른 입력대상으로부터도 행 단위로 읽어올 수 있음

    Stream<String> Files.lines(Path path)
    Stream<String> Files.lines(Path path, Charset cs)
    Stream<String> lines()    // BufferedReader클래스의 메서드

    빈 스트림 생성하기

     스트림 연산 수행 결과가 하나도 없다면, null보다는 빈 스트림을 반환하는 것이 나음

    요소가 하나도 없는 비어있는 스트림도 생성할 수 있음

    Stream emptyStream = Stream.empty();      // empty()는 빈 스트림을 생성해서 반환
    long   count       = emptyStream.count(); // count의 값은 0

     count()는 스트림 요소의 개수를 반환함

    두 스트림 연결하기

    String[] str1 = {"123", "456", "789"};
    String[] str2 = {"ABC", "DEF", "abc"};
    
    Stream<String> strs1 = Stream.of(str1);
    Stream<String> strs2 = Stream.of(str2);
    Stream<String> strs3 = Stream.concat(strs1, strs2); // 두 스트림을 하나로 연결
    반응형

    댓글

Designed by Tistory.