관리 메뉴

KorSA

[남궁성 '자바의 정석'] 164~171강 본문

Study Memos/Java

[남궁성 '자바의 정석'] 164~171강

Praiv. 2021. 11. 19. 12:24
320x100

※ 이 글은 남궁성 저자의 '자바의 정석' 164~171강을 수강한 후 정리한 내용입니다.

 

1. 람다식 iterate(), generate()
    iterate()는 이전 요소를 seed로 해서 다음 요소를 계산한다.

Stream<Integer> evenStream = Stream.iterate(0, n -> n + 2); // 0, 2, 4, 6, ...


    generate()는 seed를 사용하지 않는다.

Stream<Double> randomStream = Stream.generate(Math::random);
Stream<Integer> oneStream = Stream.generate(()->1); // 1, 1, 1, 1 ...


2. 스트림 중간 연산의 핵심은 map()과 flatmap()

3. 스트림 중간 연산 - sorted() 연산
    Comparator의 comparing()으로 정렬 기준을 제공

studentStream.sorted(Comparator.comparing(Student::getBan))
	.forEach(System.out::println);


추가 정렬 기준을 제공할 때는 thenComparing()을 사용

studentStream.sorted(Comparator.comparing(Student::getBan)
	.thenComparing(Student::getTotalScore()
	.thenComparing(Student::getName)
	.forEach(System.out::println);


4. 스트림 중간 연산 - map() 연산
    스트림의 요소를 변환한다

Stream<R> map(Function<? super T,? extends R> mapper) // Stream<T>->Stream<R>
Stream<String> filenameStream = fileStream.map(File::getName);


5. 스트림 중간 연산 - peek() 연산
    스트림 연산 중간 중간에 디버깅 용도로 많이 사용

6. 스트림 중간 연산 - flatMap()
    스트림의 스트림을 스트림으로 변환한다

Stream<String[]> strArrStrm = Stream.of(new String[]{"abc", ",def", "ghi"}, new String[] {"ABC","GHI","JKLMN"});
Stream<Stream<String>> strStrStrm = strArrStrm.map(Arrays::stream); // map()을 쓰면 Stream의 Stream 형태로 리턴된다
Stream<String> strStrStrm = strArrStrm.flatMap(Arrays::stream); // flatMap()을 쓰면 Stream형태로 리턴한다.


7. Optional<T>
    T 타입 객체의 래퍼 클래스
    null을 직접 다루는 건 NullPointerException 발생 소지가 있기 때문에 위험함.
    또 null을 그대로 쓰면 null체크등 코드가 지저분해짐.
    그래서 Optional<T>를 사용해서 null을 간접적으로 다룸.

8. null대신 빈 Optional<T> 객체를 사용하자

Optional<String> optVal = null; // 이렇게 쓰지 말자!!
Optional<String> optVal = Optional.<String>empty(); // 빈 객체로 초기화
Optional<String> optVal = Optional.empty(); // <> 생략 가능


9. Optional<T>.isPresent()
    Optional객체의 값이 null이면 false, 아니면 true를 반환

// ifPresent(Consumer) - null이 아닐 때만 작업 수행, null이면 아무 일도 안함
Optional.ofNullable(str).ifPresent(System.out::println);


10. Optional 객체의 값 가져오기 - get(), orElse(), orElseGet(), orElseThrow()

Optional<String> optVal = Optional.of("abc");
String str1 = optVal.get(); // optVal에 저장된 값을 반환. null이면 예외발생
String str2 = optVal.orElse(""); // optVal에 저장된 값이 null일 때는 ""를 반환
String str3 = optVal.orElseGet(String::new); // 람다식 사용가능 () -> new String()
String str4 = optVal.orElseThrow(NullPointerException::new); // null이면 예외발생


11. 기본형 값을 감싸는 래퍼클래스 - OptionalInt, OptionalLong, OptionalDouble
    Optional<T> 형태를 사용해도 되지만 미리 만들어진 기본형 래퍼클래스를 사용하면 성능이 높아진다.

12. 스트림 최종 연산의 핵심은 reduce()와 collect()

13. 스트림 최종 연산 - forEach()

void forEach(Consumer<? super T> action) // 병렬 스트림인 경우 순서가 보장되지 않음
void forEachOrdered(Consumer<? super T> action) // 병렬 스트림인 경우에도 순서가 보장됨


    Optional<T> findFirst() // 첫번째 요소를 반환. 순차 스트림에 사용
    Optional<T> findAny() // 아무거나 하나를 반환. 병렬 스트림에 사용

14. 스트림 최종 연산 - reduce()
    스트림의 요소를 하나씩 줄여가며 누적연산 수행

int count = intStream.reduce(0, (a,b) -> a + 1);
int sum = intStream.reduce(0, (a,b) -> a + b);
int max = intStream.reduce(Integer.MIN_VALUE, (a,b)-> a > b ? a : b); // max()
int min = intStream.reduce(Integer.MAX_VALUE, (a,b)-> a < b ? a : b); // min()


15. 스트림 최종 연산 - collect()
    collect()는 Collector를 매개변수로 하는 스트림 최종 연산
    reduce()와 거의 비슷한 역할
    object collect(Collector collector);

16. Collector 인터페이스는 수집(collect)에 필요한 메서드를 정의해 놓은 인터페이스

17. Collectors 클래스는 다양한 기능의 컬렉터(Collector 인터페이스를 구현한 클래스)를 제공

long count = stuStream.count(); // 항상 전체 count
long count = stuStream.collect(counting()); // 그룹별로 나눠서 counting할 수 있음. 여기선 그룹이 안나눠져있어서 위 코드와 같은 의미


18. 스트림의 그룹화와 분할
    partitioningBy()는 스트림을 2 분할한다. groupingBy()보다 빠르다.
    groupingBy()는 스트림을 n분할한다.

Map<Boolean, List<Student>> stuBySex = stuStream.collect(partitioningBy(Student::isMale)); // 학생들을 성별로 분할
List<Student> maleStudent = stuBySex.get(true); // 남학생 목록
List<Student> femaleStudent = stuBySex.get(false); / /여학생 목록

Map<Boolean, Long> stuNumBySex = stuStream.collect(partitioningBy(Student::isMale, counting())); // 분할 + 통계
int maleCnt = stuNumBySex.get(true); // 남학생 수
int femaleCnt = stuNumBySex.get(false); // 여학생 수

Map<Boolean, Optional<Student>> topScoreBySex = stuStream.collect(partitioningBy(Student::isMale, maxBy(comparingInt(Student::getScore)))); // 분할 + 통계
int maleTopScore = topScoreBySex.get(true); // 남학생 1등
int femaleTopScore = topScoreBySex.get(false); // 여학생 1등

Map<Boolean, Map<Boolean, List<Student>>> failedStuBySex = stuStream.collect(
	partitioningBy(Student::isMale, // 1. 성별로 분할 (남/녀)
		partitioningBy(s -> s.getScore() < 150))); // 2. 성적으로 분할 (불합격/합격)
List<Student> failedMaleStu = failedStuBySex.get(true).get(true); // 첫번째 true - 남자, 두번째 true - 불합격
List<Student> failedFemaleStu = failedStuBySex.get(false).get(true); // 첫번째 true - 여자, 두번째 true - 불합격


19. 스트림 변환표
    추후 추가 예정

728x90
728x90
Comments