-
챕터[5] 스트림 데이터 수집모던자바인액션 2020. 10. 21. 15:57
서론
스트림을 활용하여 데이터 편집
일반 스트림 필터링
// 칼로리 정렬 List<Dish> filteredMenu = specialMenu.stream() .filter(dish -> dish.getCalories() < 320) .collect(Collectors.toList());
고유 요소 필터링
// 중복제거 List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5); numbers.stream().filter(i -> i % 2 == 0) .distinct() .forEach(System.out::println);
스트림 축소
// 축소 List<Dish> limitDish = specialMenu.stream() .filter(dish -> dish.getCalories() > 0) .limit(2) .collect(Collectors.toList()); limitDish.forEach(dish -> System.out.println(dish.toString()));
스트림 건너뛰기
// 스킵 List<Dish> skipDish = specialMenu.stream() .filter(dish -> dish.getCalories() > 0) .skip(1) .collect(Collectors.toList()); skipDish.forEach(dish -> System.out.println(dish.toString()));
스트림의 각 요소에 함수 적용하기
스트림은 함수를 인수로 받는 map 메서드를 지원한다 인수로 제공된 함수는 각 요소에 적용되며 함수를 적용한 결과가 새로운 요소로 매핑된다. ( 고친다는 개념보다는 새로 만든다는 개념에 가까우무로 변환에 가까운 매핑 이라는 단어를 사용한다 )
// 요리 이름으로 List<String> 담아낸다. List<String> dishNames = specialMenu.stream() .map(Dish::getName) .collect(Collectors.toList()); dishNames.forEach(s -> System.out.println(s));
Optional?
옵셔널은 10장에서 다시 설명하기에 간단하게 설명만 쓰여있다.
null을 담을 수 있는 객체이고 메소드로는 아래와 같이 존재한다.
isPresent(): Optional이 값을 포함하면 true 값을 반환하고 값을 가지고 있지 않는다면 false를 반환한다.
ifPresent(): 값이 있으면 주어진 블럭을 실행하고 없는다면 실행하지 않는다.
get(): 값이 존재한다면 값을 반환한다.
orElse: 값이 있으면 값을 반환 없으면 그 밖의 기본값을 반환한다.
요소 검색
//요소 검색 ( 랜덤 이라 Optional ) Optional<Dish> d = specialMenu.stream() .filter(Dish::isBool) .findAny(); // 이렇게 가져온 객체 d는 값이 있을지 없을지는 모르기에 값이 있으면 출력하는 코드로 바꿀 수 있다. specialMenu.stream() .filter(Dish::isBool) .findAny() .ifPresent(dish -> System.out.println(dish.getName));
첫번째 요소 반환
// 값이 존재하면 첫번째 객체를 반환한다 Optional<Dish> d1 =specialMenu.stream() .filter(Dish::getBool) .findFirst();
reduce연산
모든 스트림 요소를 처리해서 값으로 도출하는 리듀싱 연산은 마치 과정이 작은 조각이 될 때까지 반복해서 접는다는 비슷한 의미인 폴드라고 불린다.
* 하나 이상의 초기값이 존재해야만 한다. ( Optional 리듀스는 예외 )
// 칼로리를 전부다 더하는 코드 int cal = specialMenu.stream() .map(Dish::getCalories) .reduce(0, Integer::sum);
기본형 특화 스트림
// 에러 map으로 객체를 만들어내도 그 객체는 Dish이기에 int에 담아낼 수 없다. int cal = specialMenu.stream() .map(Dish::getCalories) .sum(); // mapToInt를 사용하여 Dish객체에서 int로 변환 int calories = specialMenu.stream() .mapToInt(Dish::getCalories) .sum();
기본형: OptionalInt
// max값을 찾는코드 ( 단 특정 값을 찾는다는 뜻은 값이 없을 가능성도 존재하기에 Optinal로 받는다 ) OptionalInt maxCal = specialMenu.stream() .mapToInt(Dish::getCalories) .max(); System.out.println(maxCal);
Stream 만들기
// 입력값 소문자로 스트림 만들기 Stream<String> stream = Stream.of("BQT", "BBC", "DDE"); stream.map(String::toLowerCase).forEach(System.out::println); // 배열로 스트림 만들기 ( 합계출력 ) int[] numbers = {1, 2, 3, 4, 5}; int sum = Arrays.stream(numbers).sum();
무한스트림
iternate 메서드는 초깃값과 람다를 인수로 받아서 새로운 값을 끊임없이 생산할 수 있다. ex) n -> n+2 ( 짝수 스트림 생성 ) 0 2 4 6...
이렇게 iterate는 요청할 때마다 값을 생산할 수 있어서 무한 스트림 을 만들 수 있다. 이러한 스트림은 언 바운드 스트림 이라 표현한다.
generate 메서드는 iternate와 달리 생산된 값을 연속적으로 계산해서 만들지 않고 Supplier<T>인수를 받아서 새로운 값으로 스트림을 생산한다. * Supplier<T> 소모해야 하는 함수인터페이스 ( 즉 generate 는 객체를 계속 받아 소모하여 Stream을 만든다. )
무한스트림은 limite로 몇번을 돌릴지 정해두지 않으면 계속해서 스트림을 생산하게 된다.
'모던자바인액션' 카테고리의 다른 글
챕터[7] 스트림 병렬화 (0) 2020.10.21 챕터[6] 스트림 그룹화 (0) 2020.10.21 챕터[4] 스트림 (0) 2020.10.21 챕터[3] 람다 (0) 2020.10.21 챕터[2] 동작 파라미터화 (0) 2020.10.21