7장 : 람다와 스트림

2023. 4. 6. 14:46스터디/이펙티브 자바 스터디

728x90

아이템 42. 익명 클래스보다는 람다를 사용하라 

- 타입을 명시해야 코드가 더 명확할 때만 제외하고는, 람다의 모든 매개변수 타입은 생략

- 타입을 알 수 없다는 오류를 낼 때만 해당 타입을 명시

- 람다는 이름이 없고 문서화도 못함. 따라서 코드 자체로 동작이 명확히 설명이 되지 않거나 코드 줄 수가 많아지면 람다를 쓰면 안 됨

- 람다는 한 줄 일 때 가장 좋고, 길어야 세 줄 안에 끝내야

- 람다에서의 this 키워드는 바깥 인스턴스를 가리킴

- 함수 객체가 자신을 참조해야 한다면 반드시 익명 클래스를 써야

- 람다를 직렬화 X


아이템 43. 람다보다는 메서드 참조를 사용하라 

- 람다로 할 수 없는 일이라면 메서드 참조로도 할 수 없음


아이템 44. 표준 함수형 인터페이스를 사용하라 

 

# 함수형 인터페이스를 구현해야 하는 조건 - 하나라도 만족시 고민

1. 자주 쓰이며 이름 자체가 용도를 명확히 설명해줌

2. 반드시 따라야 하는 규약이 있음

3. 유용한 디폴트 메서드를 제공할 수 있음

 

- 직접 만든 함수형 인터페이스는 항상 @FunctionalInterface 사용- 서로 다른 함수형 인터페이스를 같은 위치의 인수로 받는 메서드들을 다중 정의해서는 안 됨


아이템 45. 스트림은 주의해서 사용하라 

- 스트림 파이프라인은 소스 스트림에서 시작, 종단 연산에서 끝

- 그 사이에 하나 이상의 중간연산이 있을 수 있음

- 스트림 파이프라인은 지연평가됨. 즉, 종단 연산이 호출될 때 연산됨

- 기본적으로 스트림 파이프라인은 순차적으로 수행

- 병렬로 실행하려면 parallel 매서드 호출해주면 되나, 효과적인 상황은 많지 않음

- 스트림을 과용하면 프로그램이 읽거나 유지보수하기 어려워짐

- char 스트림은 지원하지 않기 때문에 char 값 처리시는 스트림 삼가하는 편이 낫다

 

# 함수 객체로는 할 수 없으나, 코드 블록으로는 할 수 있는 일

1. 범위 내 지역 변수를 읽고 수정 가능

2. return문을 통해 메서드에서 빠져나가거나 vreak나 contunue문으로 블록 밖 반복문을 종료

3. 메서드 선언에 명시된 검사 예외

 

# 스트림 안성 맞츰

1. 윈소들의 시퀀스를 일관되게 변환

2. 원소들의 시퀀스를 필터링

3. 원소들의 시퀀스를 하나의 연ㅅ난을 사용해 결합

4. 원소들의 시퀀스를 컬렉션에 모음

5. 원소들의 시퀀스에서 특정 조건을 만족하는 원소를 탐색

 

# 스트림이 하기 어려운 일

- 한 데이터 파이프라인의 여러 단계를 통과시 이 테이터의 각 단계에서 값들에 동시에 접근하기 어려운 경우

- 스트림은 일단 한 값을 다른 값에 매핑하고 나면 원래 값을 잃음

 

- 스트림을 반환하는 메서드 이름은 원소의 정체를 알려주는 복수 명사로 쓰기를 추천

아이템 46. 스트림에서는 부작용 없는 함수를 사용하라 

- 스트림 패러다임의 핵심은 일련의 변환으로 재구성하는 부분 - 각 변환 단계는 가능한 이전 단계의 결과를 받아 처리하는 순수 함수여야- 함수 객체는 모두 부작용이 없어야


아이템 47. 반환 타입으로는 스트림보다 컬렉션이 낫다 

- 스트림은 반복을 지원하지 않음

- Stream 인터페이스는 Iterable 인터페이스가 정의한 추상 메서드를 전부 포함할 뿐 아니라, Iterable 인터페이스가 정의한 방식대로 동작 

- API가 Iterable만 반환하면 이를 스트림 파이프라인에서 처리

- 반환된 객체들이 반복문에서만 쓰일걸 알면 Iterable을 반환

- 원소 시퀀스를 반환하는 공개 API의 반환 타입에는 Collection이나 그 하위 타입을 쓰는게 일반적으로 최선

- 단지 컬렉션을 반환한다는 이유로 덩치 큰 시퀀스를 메모리에 올려서는 안 됨

- contains나 size를 구현하는게 불가능할 때는 컬랙션 보다는 스트림이나 Iterable을 반환하는 것이 낫다

- 반복을 사용하는게 더 자연스러운 상황에서도 사용자는 그냥 스트림을 쓰거나 Iterable로 변환해주는 어댑터를 이용


아이템 48. 스트림 병렬화는 주의해서 적용하라 

- 자바8부터 parallel 메서드만 한 번 호출하면 파이프라인을 병렬 실행할 수 있는 스트림을 지원

- 동시성 프로그래밍을 할 때는 안전성과 응답 가능 상태를 유지하기 위해 애써야

- 데이터 소스가 Stream.iterate거나 중간 연산으로 limit를 쓰면 파이프라인 병렬화로는 성능 개선을 기대할 수 없음

- 스트림 파이프라인을 마구잡이로 병렬화 하면 안 됨

- 대체로 스트림의 소스가 ArrayList, HashMap, HashSet, ComcurrentHashMap의 인스턴스거나 배열, int범위, long 범위일 때 병렬화의 효과가 가장 좋음

- 위 자료구조들은 순차적으로 실행시 참조 지역성이 뛰어남

- 순차적인 연산이라면 파이프라인 병렬 수행의 효과는 제한될 수 밖에 없음

- 종단 연산 중 병렬화에 가장 적합한 것은 축소다

- ex) reduce, min, max, count, sum 같이 완성된 형태로 제공하는 메서드

- ex) anyMatch, allMatch, noneMatch 같이 조건에 맞으면 바로 반환되는 메서드

- Stream 의 collect는 병렬화에 적합하지 않음. 컬랙션들을 합치는 부담이 크기 때문

- 스트림을 잘못 병렬화하면 성능이 나빠질 뿐 아니라 결과 자체가 잘못될 수도

- 스트림 병렬화는 오직 성능 최적화 수단임

- 성능을 테스트하여 병렬화의 가치를 판단해야

- Random 연산은 모든 연산을 동기화하기 때문에 병렬 처리하면 최악의 성능을 보임

728x90

'스터디 > 이펙티브 자바 스터디' 카테고리의 다른 글

9장 : 일반적인 프로그래밍 원칙  (0) 2023.04.15
8장 : 메서드  (0) 2023.04.06
6장 : 열거 타입과 애너테이션  (0) 2023.04.06
5장 : 제네릭  (0) 2023.04.06
4장 : 클래스와 인터페이스  (0) 2023.04.06