// 전체 리스트 순회
List<Car> filterCar = carList.stream()
.filter(car -> car.getPrice() < 3000)
.collect(toList());
// 조건에 맞지 않으면 Stop
List<Car> filterCar = carList.stream()
.takeWhile(car -> car.getPrice() < 3000)
.collect(toList());
// 처음으로 거짓이 되는 지점까지 버림.
List<Car> filterCar = carList.stream()
.dropWhile(car -> car.getPrice() < 3000)
.collect(toList());
스트림은 주어진 값 이하의 크기를 갖는 새로운 스트림을 반환하는 limit(n) 메서드를 지원한다.
// 3개 요소 반환
List<Car> filterCar = carList.stream()
.filter(car -> car.getPrice() < 3000)
.limit(1)
.collect(toList());
// 처음 3개 요소 건너뛰기
List<Car> filterCar = carList.stream()
.filter(car -> car.getPrice() < 3000)
.skip(3)
.collect(toList());
// 자동차 이름을 추출하는 예제
List<String> carNames = car.stream()
.map(Car::getName)
.collect(toList());
// 단어 리스트의 글자수 추출
List<String> words = Arrays.asList("모자인", "스터디", "화이팅");
List<Integer> wordLengths = words.stream()
.map(String::length)
.collect(toList());
// map 을 연결하여 자동차 이름 글자수 추출
List<String> carNames = car.stream()
.map(Car::getName)
.map(String::length)
.collect(toList());
[“Hello”, “World”]
리스트가 [“h”, “e”, “l”, “o”, “W”, “r”, “d”]
가 되도록 변경하는 것이다.words.stream()
.map(word -> word.split(""))
.distinct()
.collect(tolist())
Stream<String[]>
이 될것이다. 원하는 결과는 Stream인데 어떻게 구현헤야 할지 생각 해보자.List<String> uniqueCharacters = words.stream()
.map(word -> word.split("")) // 각 단어를 개별 문자를 포함하는 배열로 변환
.flatMap(Arrays::stream) // 생성된 스트림을 하나의 스트림으로 평면화
.distinct()
.collect(toList());
스트림은 allMatch, anyMatch, noneMatch, findFirst, findAny등 다양한 유틸리티 메서드를 지원한다.
anyMatch
: Predicate가 적어도 한 요소와 일치 하는지 확인boolean isMatch = menu.stream().anyMatch(Dish::isVegetarian)
allMatch
: Predicate가 모든 요소와 일치하는지 검사boolean allMatch = menu.stream().allMatch(Dish::isVegetarian)
NoneMatch
: allMatch와 반대 연산findAny 메서드는 현재 스트림에서 임의의 요소를 반환한다. findAny 메서드를 다른 스트림 연산과 연결해서 사용할 수 있다.
// filter 와 findAny를 활용해 채식 요리를 선택하는 방법
Optional<Dish> dish = words.stream()
.filter(Dish::isVegetarian)
.findAny();
Optional은 10장에서~
리스트 또는 정렬된 데이터로 부터 생성된 스트림은 논리적인 아이템 순서가 정해져 있을 수 있다. 이런 스트림에서 첫번째 요소를 찾기 위한 방법은 findFirst를 사용하는 것이다.
// 3으로 나누어 떨어지는 첫 번째 제곱근 값을 반환하는 코드.
List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5);
Optional<Integer> first = someNumbers.stream()
.map(n -> n * n)
.filter(n -> n % 3 == 0)
.findFirst();
두 개의 메서드를 모두 제공하는 이유는 병렬성 때문이다. 병렬 실행에서는 첫번째 반환 요소를 선택하기 어려우니 반환 순서가 상관이 없다면 병렬 스트림에서 제약이 적은 findAny를 주로 사용한다.
스트림의 최종연산 중 하나로 마지막 결과가 나올때까지 스트림의 모든 요소를 반복적으로 처리하는 과정
함수형 프로그래밍 언어 용어로는 이과정이 마치 종이를 작은 조각이 될때까지 반복해서 접는것과 비슷하다 하여 폴드라고 부른다.
reduce 메서드를 살펴보기 전에 for-each 루프를 이용해 리스트의 숫자 요소를 더하는 코드를 확인
int sum = 0;
for (int x : numbers) {
sum += x;
}
int sum = numbers.stream().reduce(0, (a, b) -> a + b);
BinaryOperator
. 예제에서는 람다 표현식 (a, b) -> a + b
를 사용했다.reduce
로 다른 람다, 즉 (a, b) -> a * b
를 넘겨주면 모든 요소에 곱셈을 적용할 수 있다.int sum = numbers.stream().reduce(0, Integer::sum);
Optional sum = numbers.stream().reduce((a, b) -> a + b);
Optional max = numbers.stream().reduce(Integer::max);
Optional min = numbers.stream().reduce(Integer::min);
(x, y) -> x > y ? x : y;
int calories = menu.stream()
.mapToInt(Dish::getCalories)
.sum();
IntStream intStream = menu.stream().mapToInt(Dish::getCalories);
Stream<Integer> stream = intStream.boxed();
IntSteram.rangeClose(1, 100)
// 1 ~ 100 의 숫자 범위를 만든다.range()
는 열려있는 연산을 하기 때문에 마지막 숫자가 범위에 포함되지 않는다.Stream.of(“Modern “, “Java”, “In”, “Action”);
Stream<String> homeValueStream = Stream.ofNullable(System.getProperty("home"));
Stream<String> values = Stream.of("config", "home", "user")
.flatMap(key -> Stream.ofNullable(System.getProperty(key)))
int[] nubmers = {1, 2, 3, 4, 5};
int sum = Arrays.stream(numbers).sum();
Stream.iterate(0, n -> n + 2)
.limit(10)
.forEach(System.out::println)
iterate 메서드는 초깃값과 람다를 활용하여 스트림을 생성 할 수 있다. 이때 생성되는 스트림은 무한적이기 때문에 반드시 limit과 같은 메서드를 사용하여 범위를 지정해주어야 한다.
iterate는 순차적으로 실행되며 무한적으로 생성되는 스트림을 언바운드 스트림이라고 표현한다.
Java 9 부터는 iterate 에서 Predicate를 지원한다.
// 0 부터 시작하여 100 보다 작은 수의 스트림 생성
Stream.iterate(0, n -> n < 100, n -> n + 2)
.forEach(System.out::println)
// 아래와 같은 방법은 사용할 수 없다. 스트림의 종료시점을 알수 없기 때문이다 .
Stream.iterate(0, n -> n + 2)
.filter(n -> n < 100)
.forEach(System.out::println)
// 스트림 쇼트서킷을 지원하는 takeWhile을 사용하는것이 해법이다.
Stream.iterate(0, n -> n + 2)
.takeWhile(n -> n < 100)
.forEach(System.out::println)
Stream.generate(Math::random)
.limit(5)
.forEach(System.out::println)