// 스트림 인터페이스의 filter 메서드는 Predicate를 인수로 받고, // 일치하는 모든 요소를 반환한다. List<Dish> vegetarianMenu = menu.stream() .filter(Dish::isVegetarian) .collect(toList());
// ** 고유 요소 필터링 ** // distinct 메서드로 중복을 제거한다. List<Integer> numbers = Arrays.asList(1, 2, 1, 3, 3, 2, 4); numbers.stream() .filter(i -> i % 2 == 0) .distinct() .forEach(System.out::println); // 2, 4 출력
// ** Predicate가 적어도 한 요소와 일치하는지 확인 ** // 메뉴 중 채식주의자 용 메뉴가 하나라도 존재하면 메세지 출력 if (menu.stream().anyMatch(Dish::isVegetarian)) { System.out.println("The menu is (somewhat) vegetarian friendly!!"); }
// ** Predicate가 모든 요소와 일치하는지 검사 ** // 모든 메뉴가 1000 칼로리 미만인지 확인 boolean isHealthy = menu.stream() .allMatch(d -> d.getCalories() < 1000); boolean isHealthy = menu.stream() .noneMatch(d -> d.getCalories() >= 1000);
// ** 임의의 요소 검색 ** // 채식 요리 선택 Optional<Dish> dish = menu.stream() .filter(Dish::isVegetarian) .findAny() .ifPresent(d -> System.out.println(d.getName()));
// ** 첫 번째 요소 검색 ** List<Integer> someNumbers = Arrays.asList(1, 2, 3, 4, 5); Optional<Integer> firstSquareDivisibleByThree = someNumbers.stream() .map(n -> n * n) .filter(n -> n % 3 == 0) .findFirst(); // 9
리듀싱
reduce()
reduce 메서드는 병렬 처리가 가능하다는 장점이 있다.
1 2 3 4 5 6 7 8 9 10 11 12 13 14
// ** 요소의 합 ** // before int sum = 0; for (int x : numbers) { sum += x; } // after int sum = numbers.steam().reduce(0, (a, b) -> a + b); int sum = numbers.steam().reduce(0, Integer:sum); // 메서드 레퍼런스 사용 Optional<Integer> sum = numbers.stream().reduce((a, b) -> (a + b)); // 초기값을 받지 않는 방법 (Optional 객체로 반환)
// ** 최대값과 최소값 ** Optional<Integer> max = numbers.stream().reduce(Integer::max); Optional<Integer> min = numbers.stream().reduce(Integer::min);
연산
형식
반환 형식
사용된 함수형 인터페이스 형식
함수 디스크립터
filter
중간 연산
Stream
Predicate
T -> boolean
distinct
중간 연산 (상태 있는 언바운드)
Stream
skip
중간 연산 (상태 있는 언바운드)
Stream
Long
limit
중간 연산 (상태 있는 언바운드)
Stream
Long
map
중간 연산
Stream
Function<T, R>
T -> R
flatMap
중간 연산
Stream
Function<T, Stream>
T -> Stream
sorted
중간 연산 (상태 있는 언바운드)
Stream
Comparator
(T, T) -> int
anyMatch
최종 연산
boolean
Predicate
T -> boolean
noneMatch
최종 연산
boolean
Predicate
T -> boolean
allMatch
최종 연산
boolean
Predicate
T -> boolean
findAny
최종 연산
Optional
findFirst
최종 연산
Optional
forEach
최종 연산
void
Consumer
T -> void
Collect
최종 연산
R
Collector<T, A, R>
Reduce
최종 연산 (상태 있는 언바운드)
Optional
BinaryOperator
(T, T) -> T
count
최종 연산
long
숫자형 스트림
기본형 특화 스트림
Java8에는 박싱 비용을 줄이고 sum, max와 같이 자주 사용되는 숫자 관련 리듀싱 연산 메서드를 함께 제공하는 세 가지 기본형 특화 스트림을 제공한다.
IntStream
DoubleStream
LongStream
OptionalInt
OptionalDouble
OptionalLong
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
// ** 숫자 스트림으로 매핑 ** // mapToInt 메서드는 IntStream 인터페이스로 반환하며, // 기본적으로 sum, min, average 등 다양한 유틸리티 메서드를 제공한다. int calories = menu.stream() .mapToInt(Dish::getCalories) .sum();
// **객체 스트림으로 복원 ** // boxed() 메서드를 사용하여 특화 스트림을 일반 스트림으로 변환할 수 있다. IntStream intStream = menu.stream().mapToInt(Dish::getCalories); Stream<Integer> stream = intStream.boxed();
// Optional 컨테이너 클래스 OptionalInt maxCalories = menu.stream() .mapToInt(Dish::getCalories) .max(); int max = maxCalories.orElse(1); // 값이 없을 때 기본 최대값을 명시적으로 설정
숫자 범위
IntStream과 LongStream은 특정 범위의 숫자를 이용하기 위한 2가지 정적 메서드를 제공한다. :
int[] numbers = {2, 3, 5, 7, 11, 13}; int sum = Arrays.stream(numbers).sum(); // 합계 41
파일로 스트림 만들기
NIO API(비블록 I/O)도 스트림 API를 활용할 수 있게 되었다. java.nio.file.Files의 많은 정적 메서드가 스트림을 반환한다. (ex> Files.lines)
1 2 3 4 5 6 7 8 9 10
// 파일에서 고유한 단어 수를 찾는 프로그램 // Files.lines 메서드는 주어진 파일의 행 스트림을 문자열로 반환한다. long uniqueWords = 0; try (Stream<String> lines = Files.lines(Paths.get("data.txt"), Charset.defaultCharset())) { uniqueWords = lines.flatMap(line -> Arrays.stream(line.split(" "))) .distinct() .count(); } catch (IOException e) { }
함수로 무한 스트림 만들기
스트림 API는 함수에서 스트림을 만들 수 있는 두 개의 정적 메서드를 제공한다. 이전에 봤던 크기가 고정된 컬렉션과는 달리 크기가 고정되지 않은 무한 스트림(Infinite Stream) 을 만들 수 있다. (언바운드 스트림(Unbounded Stream)) 따라서 반드시 limit(n) 함수와 함께 사용해야 한다.
Stream.iterate()
초기값과 람다를 인수로 받아서 새로운 값을 끊임없이 생산한다.
일반적으로 연속된 일련의 값을 만들 때 사용한다.
Stream.generate()
Supplier를 인수로 받아서 새로운 값을 생산한다.
1 2 3 4 5 6 7 8 9
// iterate Stream.iterate(0, n -> n + 2) .limit(10) .forEach(System.out::println); // 0, 2, 4, 6, 8, 10, 12, 14, 16, 18 출력
近期评论