스트림에 정의된 메서드 중에서 데이터 소스를 다루는 작업을 수행하는 것을 연산 (Operation)이라고 한다.
스트림이 제공하는 연산은 중간 연산과 최종 연산으로 분류할 수 있는데, 중간 연산은 연산 결과를 스트림으로 반환하기 때문에 연속해서 연결할 수 있다. 반면, 최종 연산은 스트림의 요소를 소모하면서 연산을 수행하므로 단 한번만 연산이 가능하다.
💡 중간 연산
: 연산 결과가 스트림인 연산, 스트림에 연속해서 중간 연산할 수 있음
최종 연산
: 연산 결과가 스트림이 아닌 연산. 스트림의 요소를 소모하므로 단 한번만 가능
스트림은 데이터 소스로부터 데이터를 읽기만할 뿐 변경하지 않는다. (Read Only)
스트림은 Iterator처럼 일회용이다.
최종 연산 전까지 중간연산이 수행되지 않는다. - 지연된 연산
IntStream intStream = new Random().ints(1, 46);
intStream.distinct().limit(6).sorted()
.forEach((i->System.out.print(i+", ")));
스트림은 작업을 내부 반복으로 처리한다.
stream.forEach(System.out::println);
sequantial()
: parallel()을 호출한 것을 취소할 때만 사용한다.int sum = strStream.**parallel()** //병렬스트림으로 전환
.mapToInt(s -> s.length()).sum(); //모든 문자열 길이의 합
Collection에는 stream()이 정의되어 있다. 그래서 Collection의 자손인 List와 Set을 구현한 컬렉션 클래스들은 모두 이 메서드로 스트림을 생성할 수 있다.
Stream<T> Collction.stream()
List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);
Stream<Integer> intStream = list.stream();
배열을 소스로 하는 스트림을 생성하는 메서드는 Stream과 Arrays에 Static 메서드로 정의되어 있다.
Stream<T> Stream.of(T1, T2, ...) //가변인자
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 IntStream.of(1, 2, ..)
IntStream IntStream.of(int[])
IntStream Arrays.Stream(int[])
지정된 범위의 연속된 정수를 스트림으로 생성
IntStream IntStream.range(int begin, int end) //end 불포함
IntStream IntStream.rangeClosed(int begin, int end) //end 포함
IntStream.range(1, 5).forEach(System.out::println);
//결과
1
2
3
4
Random 클래스에는 아래와 같은 인스턴스 메서드들이 있다. 이 메서드들은 해당 타입의 난수들로 이루어진 스트림을 반환한다.
IntStream ints()
LongStream longs()
DoubleStream doubles()
위 메서드들은 스트림의 크기가 정해지지 않은 ‘무한 스트림(Infinite stream)’이므로 limit()으로 크기를 제한하거나, 매개변수로 스트림의 크기를 지정해야 한다.
Int Stream intStream = new Random().ints(); //무한 스트림
IntStream.limit(5).forEach(System.out::println);
IntStream ints(long streamSize)
LongStream longs(long streamSize)
DoubleStream doubles (long streamSize)
생성된 스트림은 아래와 같은 범위를 가지지만, 지정된 범위의 난수를 발생시킬 수도 있다.
IntStream ints(int begin, int end) //무한 스트림
IntStream ints(long streamSize, int begin, int end) //유한 스트림
static <T> Stream<T> iterate(T seed, UnaryOperator<T> f)
static <T> Stream<T> generate(Supplier<T> s)
//0, 2, 4, 6,...
Stream<Integer> evenStream = Stream.iterate(0, n->n+2);
//lambdda
Stream<Double> randomStream = Stream.generate(Math::random);
//1, 1, 1,...
Stream<Integer> oneStream = Stream.generate(()->1);
Stream<Path> Files.list(Path dir) //Path는 파일 또는 디렉토리
Stream<String> Files.lines(Path path)
Stream<String> Files.lines(Path path, Charset cs)
Stream<String> lines() //BufferedReader 클래서의 메서드
Stream emptyStream = Stream.empty();
long count = emptyStream.count(); //count 값은 0
Stream의 static 메서드인 concat()을 사용하면 두 스트림을 하나로 연결할 수 있다.