/ JAVAJUNGSUK

Ch14-17~22. 스트림 만들기

자바의 정석 기초편

0. 목차



Chapter14. 람다와 스트림

Ch14 - 17. 스트림 만들기 : 컬렉션

Ch14 - 18. 스트림 만들기 : 배열

Ch14 - 19. 스트림 만들기 : 임의의 수

Ch14 - 20. 스트림 만들기 : 특정 범위의 정수

Ch14 - 21. 스트림 만들기 : 람다식 iterate(), generate()

Ch14 - 22. 스트림 만들기 : 파일과 빈 스트림



Ch14 - 17. 스트림 만들기 : 컬렉션


▶ Collection으로 부터 스트림을 만드는 방법

▷ Collection 인터페이스의 stream()으로 컬렉션을 데이터 소스로 하는 스트림 생성
Stream<E> stream() // Collection 인터페이스의 메서드
▷ 예시
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> intStream = list.stream(); // list를 데이터 소스로 하는 새로운 스트림 생성

// 스트림의 모든 요소를 출력
intStream.forEach(System.out::print); // forEach = 최종 연산, 12345를 출력
intStream.forEach(System.out::print); // ERROR, 최종 연산까지 다 한 스트림은 닫힘 

// 스트림을 하나 더 생성하여 다시 출력
intStream = list.stream(); // list로부터 stream을 생성
intStream.forEach(System.out::print); // 12345 출력



Ch14 - 18. 스트림 만들기 : 배열


▶ 객체 배열로부터 스트림 생성하는 방법

▷ ()에 가변 인자를 넣어 스트림 생성
  • Stream<T> Stream.of(T...values)
▷ ()에 T[] 배열을 넣어 스트림 생성
  • Stream<T> Stream.of(T[]])
▷ ()에 T[] 배열을 넣어 스트림 생성
  • Stream<T> Arrays.stream(T[])
▷ ()에 범위를 넣어 스트림 생성
  • Stream<T> Arrays.stream(T[] array, int startInclusive, int endExclusive)
    • 배열의 일부로만 stream을 생성
    • (T[] array, from, to)
    • from ≤ 범위 < to

▷ 예시
Stream<String> strStream1 = Stream.of("a", "b", "c"); // 가변 인자
Stream<String> strStream2 = Stream.of(new String[]{"a", "b", "c"}); // 배열
Stream<String> strStream3 = Arrays.stream(new String[]{"a", "b", "c"}); // 배열
Stream<String> strStream4 = Arrays.stream(new String[]{"a", "b", "c"}, 0, 3); // 배열의 범위
String[] strArr = {"a", "b", "c"};
Stream<String> strStream3 = Arrays.stream(strArr); // 배열
		
// 위의 두 줄을 합친 것		
Stream<String> strStream3 = Arrays.stream(new String[]{"a", "b", "c"}); 


▶ 기본형 배열로부터 스트림 생성하는 방법

▷ ()에 가변 인자를 넣어 스트림 생성
  • IntStream IntStream.of(int...values)
▷ ()에 T[] 배열을 넣어 스트림 생성
  • IntStream IntStream.of(T[]])
▷ ()에 T[] 배열을 넣어 스트림 생성
  • IntStream Arrays.stream(T[])
▷ ()에 범위를 넣어 스트림 생성
  • IntStream Arrays.stream(T[] array, int startInclusive, int endExclusive)
▷ 예시
IntStream IntStream1 = IntStream.of(1, 2, 3); // 가변 인자
IntStream IntStream2 = IntStream.of(new int[]{1, 2, 3}); // 배열
IntStream IntStream3 = Arrays.stream(new int[]{1, 2, 3}); // 배열
IntStream IntStream4 = Arrays.stream(new int[]{1, 2, 3}, 0, 3); // 배열의 범위


▶ 실습

▷ 객체 배열로부터 스트림 생성
String[] strArr = {"a", "b", "c"};
		
Stream<String> strStream1 = Stream.of(strArr); // 가변 인자
Stream<String> strStream2 = Stream.of(strArr); // 배열
Stream<String> strStream3 = Arrays.stream(strArr); // 배열
Stream<String> strStream4 = Arrays.stream(strArr, 0, 2); // 배열의 범위

System.out.print("\nstrStream1 : ");
strStream1.forEach(System.out::print);
...
		
// console
strStream1 : abc
strStream2 : abc
strStream3 : abc
strStream4 : ab
▷ 기본형 배열로부터 스트림 생성
IntStream IntStream1 = IntStream.of(1, 2, 3); // 가변 인자
IntStream IntStream2 = IntStream.of(new int[]{1, 2, 3}); // 배열
IntStream IntStream3 = Arrays.stream(new int[]{1, 2, 3}); // 배열
IntStream IntStream4 = Arrays.stream(new int[]{1, 2, 3}, 0, 3); // 배열의 범위

System.out.print("\nIntStream1 : ");
IntStream1.forEach(System.out::print);
...

// console
IntStream1 : 123
IntStream2 : 123
IntStream3 : 123
IntStream4 : 123
▷ 기본형 배열이 아닌 넣어서 스트림 생성하면?
Integer[] intArr = {5, 6, 7}; // int[]는 안 됨 Integer[]!
		
Stream<Integer> IntegerStream1 = Stream.of(intArr); // 가변 인자
Stream<Integer> IntegerStream2 = Stream.of(intArr); // 배열
Stream<Integer> IntegerStream3 = Arrays.stream(intArr); // 배열
Stream<Integer> IntegerStream4 = Arrays.stream(intArr, 0, 2); // 배열의 범위

System.out.print("\nIntegerStream1 : ");
IntegerStream1.forEach(System.out::print);
...

// console
IntegerStream1 : 567
IntegerStream2 : 567
IntegerStream3 : 567
IntegerStream4 : 56
  • Integer[] intArr = {5, 6, 7};
  • 사실상, new Integer(5), new Integer(6), new Integer(7) 이게 들어 있는 것
▷ Stream vs IntStream
  • Stream<Integer>에서 제공하는 기능 사용
    Integer[] intArr = {5, 6, 7};
              
    Stream<Integer> IntegerStream1 = Stream.of(intArr);
      
    System.out.println("average : " + IntegerStream1.average()); // average : OptionalDouble[6.0] 출력
    System.out.println("sum : " + IntegerStream1.sum()); // sum : 18 출력
    System.out.println("count : " + IntegerStream1.count()); // count : 3 출력
    

    Stream<Integer>average(), sum(), count() 제공

  • IntStream에서 제공하는 기능 사용
      int[] intStreamArr = {5, 6, 7};
        
      IntStream IntStream1 = IntStream.of(intStreamArr);
        
      System.out.println("average : " + IntStream1.average()); // ERROR
      System.out.println("sum : " + IntStream1.sum()); // ERROR
      System.out.println("count : " + IntStream1.count()); // count : 3
    

    IntStreamcount()만 제공



Ch14 - 19. 스트림 만들기 : 임의의 수


▶ 난수를 요소로 갖는 스트림 생성하는 방법

▷ Random() 클래스 안에 정의 된 메서드 : 전범위
// ints()
Integer.MIN_VALUE <= ints() <= Integer.MAX_VALUE // Integer 최소값 ~ Integer 최대값, 사실상 전범위

// longs()
Long.MIN_VALUE <= longs() <= Long.MAX_VALUE

// doubles()
0.0 <= doubles() < 1.0
▷ 예시
IntStreamintStream = new Random().ints(); // 무한 스트림
intStream.limit(5).forEach(System.out::println); // 5개의 요소만 출력

IntStream intStream = new Random().ints(5); // 크기가 5인 난수 스트림을 반환
▷ Random() 클래스 안에 정의 된 메서드 : 지정 된 범위
// 무한 스트림
IntStream ints(int begin, int end)
LongStream longs(long begin, long end)
DoubleStream doubles(doubles begin, doubles end)

// 유한 스트림
IntStream ints(long streamSize, int begin, int end)
LongStream longs(long streamSize, long begin, long end)
DoubleStream doubles(long streamSize, doubles begin, doubles end)
▷ 예시
  • 무한 스트림
    public static void main(String[] args) {
      
      IntStream intStream = new Random().ints(); // 무한 스트림
        
      intStream
      .limit(10) // 10개로 잘라주지 않으면 무한 스트림이라 계속 나옴
      .forEach(System.out::println);
    }
      
    // console
    -153699236
    -1092304517
    316377933
    2143750017
    -2142552547
    627585495
    894908480
    1368624216
    -382157223
    -1926506540
      
    
  • 유한 스트림
    public static void main(String[] args) {
      
      IntStream intStream = new Random().ints(10, 5, 10); // 유한 스트림, (10개만 출력, 5에서, 10-1까지)
        
      intStream
      .forEach(System.out::println);
    }
      
    // console
    9
    6
    9
    5
    9
    9
    5
    7
    8
    5
    



Ch14 - 20. 스트림 만들기 : 특정 범위의 정수


▶ 특정 범위의 정수를 요소로 갖는 스트림 생성하는 방법

IntStream.range() : from ≤ 범위 < to(to 값 미포함)
IntStream intStream = IntStream.range(1, 5); // 1, 2, 3, 4
IntStream.rangeClosed() : from ≤ 범위 ≤ to(to 값 포함)
IntStream intStream = IntStream.rangeClosed(1, 5); // 1, 2, 3, 4, 5



Ch14 - 20. 스트림 만들기 : 람다식 iterate(), generate()


▶ 람다식을 데이터 소스로 하는 스트림 생성하는 방법

▷ 이전 요소에 종속적 : iterate()
iterate() : 이전 요소를 seed로 해서 다음 요소를 계산
iterate()의 매개변수 : iterate(T seed, UnaryOperator f) // 초기값, 단항 연산자(입력1, 출력1)
Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6...

// 초기값이 0인 n -> n + 2 계산 원리
0 -> 0 + 2
2 -> 2 + 2 
4 -> 4 + 2
6 -> 6 + 2
... // 무한 스트림
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f) // 무한 스트림, limit 같은 걸로 자르기 필요
▷ 이전 요소에 독립적 : generate()
generate() : seed 사용하지 않음
generate()의 매개변수 : generate(Supplier s) // 입력0, 출력1
Stream<Double> randomStream = Stream.generate(Math::random);
Stream<Integer> oneStream = Stream.generate(0 -> 1); // 1, 1, 1, 1, 1, 1... 무한 스트림
static <T> Stream<T> generate(Supplier<T> s) // 무한 스트림, limit 같은 걸로 자르기 필요


▶ 실습

iterate()로 홀수 10개 출력
public static void main(String[] args) {
  Stream<Integer> intStream = Stream.iterate(1, n -> n + 2); // 짝수는 초기값 '0'으로 주면 됨
  intStream.limit(10).forEach(System.out::println); // 무한 스트림이기 때문에 limit으로 10개 자르기 해 줌
}

// console
1
3
5
7
9
11
13
15
17
19
generate()로 ‘101’을 10개 출력
public static void main(String[] args) {
  Stream<Integer> intStream = Stream.generate(() -> 101);
  intStream.limit(10).forEach(System.out::println);
}

// console
101
101
101
101
101
101
101
101
101
101



Ch14 - 20. 스트림 만들기 : 파일과 빈 스트림


▶ 파일을 소스로 하는 스트림 생성하는 방법

▷ 파일 또는 디렉토리 경로를 주면 그것으로 스트림을 생성
Stream<Path> Files.list(Path dir) // Path에 파일 또는 디렉토리 작성
▷ lines() : 파일 내용을 라인 단위로 String으로 읽어 스트림을 생성
Stream<String> Files.lines(Path path)
Stream<String> Files.lines(Path path, Charset s)
Stream<String> lines() // BufferedReader 클래스의 메서드


▶ 비어있는 스트림 생성하는 방법

▷ empty() : 빈 스트림을 생성하여 반환
Stream emptyStream = Stream.empty();
long count = emptyStream.count();