람다와 스트림
1.스트림
1) Optional<T>
래퍼 클래스(Wrapper Class)는
8개의 기본 타입에 해당하는 데이터를 객체로 표현하기 위해 포장해주는 클래스
Optional<T>는 T타입의 객체를 감싸는 래퍼 클래스이다.
따라서 Optional타입의 객체에는 모든 타입의 객체를 담을 수 있다.
최종 연산의 결과를 그냥 반환하는 게 아니라,
Optional 객체에 담아서 반환하면
그 결과가 null인지 체크하는 if문 없어도 NullPointerException이 발생하지 않는다.
간결하고 편리하다.
① Optional<T> 객체 생성하기
of 또는 ofNullable()을 사용한다.
String str =”abc”;
Optional<String> optVal = Optional.of(str);
Optional<String> optVal = Optional.of(“abc”);
Optional<String> optVal = Optional.of(new String(“abc”);
만약 참조변수 값이 null일 가능성이 있다면 of()대신 ofNullable을 사용해야 한다.
Optional<String> optVal = Optional.of(null); //NullPointerException발생
Optional<String> optVal = Optional.ofNullable(null); //Ok
만약 Optional<T>타입의 참조변수를 기본값으로 초기화할 때 empty()를 사용한다.
null로 초기화하는 것이 가능하지만 empty()로 초기화하는 것이 바람직하다.
Optional<String> optVal = Optional.<String>empty(); //빈 객체로 초기화
② Optional<T> 객체의 값 가져오기
Optional 객체에 저장된 값을 가져올 때 get()을 사용한다
단, 값이 null일 경우를 대비하여 orElse()로 값을 지정할 수 있다.
Optional<String> optVal =Optional.of(“abc”);
String str1 = optVal.get(); //optVal에 지정된 값을 반환.null이면 예외 발생
String str2 =optVal.orElse(“”); //optVal에 저장된 값이 null일 때는, “”를 반환
orElse의 변형으로 null을 대체할 값을 반환하는 람다식을 지정할 수 있다.
orElseGet()과 null일 때 예외를 발생시키는 orElseThrow()가 있다.
String str3 = optVal2.orElse(String::new); //() -> new String()과 동일
String str4 = optVal2.orElseThrow(NullPointerException::new); //널이면 예외 발생
isPresent() 는 Optional객체의 값이 null이면 false, 아니면 true를 반환한다
ifPresent() (Consumer<T> block)은 값이 있으면 주어진 람다식을 실행하고,
없으면 아무 일도 하지 않는다.
예시) 다음과 같은 조건문이 있다.
if(str != null) {System.out.println(str);}
isPresent()를 이용해 이렇게 작성할 수 있다.
if(Optional.ofNullable(str).isPresent()) {System.out.println(str)}
ifPresent()를 통해 보다 간결할 수 있다.
Optional.ofNullable(str).ifPresent(System.out::println);
참조변수 str이 null이 아니면 값을 출력하고, null이면 아무 일도 일어나지 않는다.
③ OptionalInt, OptionalLong, OptionalDouble
IntStream과 같은 기본형 스트림의 최종 연산의 일부는
Optional 대신 OptionalInt, OptionalLong, OptionalDouble을 반환한다.
기본형 int의 기본값은 0이므로
아무런 값을 갖지 않는 OptionalInt에 저장된 값은 0일 것이다.
OptionalInt opt = OptionalInt.of(0) ; //OptionalInt에 0을저장
OptionalInt opt2 = OptionalInt.empty();
저장된 값이 없는 것과 0인 것은 isPresent를 통해 구분 가능하다.
System.out.println(opt.isPresent()); //true
System.out.println(opt2.isPresent()); //false
System.out.println(opt.equals(opt2)); //false

2) 스트림의 최종연산
스트림의 최종연산은 스트림의 요소를 모두 소모한 결과이다.
이로 인해 최종연산 후 스트림은 닫히며, 더이상 사용될 수 없다.
① 스트림의 최종 연산 - 조건검사
boolean allMatch (Predicate < ? super T> predicate> 모든 요소가 일치하면 참
boolean anyMatch (Predicate < ? super T> predicate> 하나의 요소라도 일치하면 참
boolean noneMatch (Predicate < ? super T> predicate> 모든 요소가 불일치하면 참
Optional<T> findfirst() 조건에 일치하는 첫번째 요소를 반환
Optional<T> findAny() 조건에 일치하는 요소를 하나 반환(병렬 스트림)
cf. findFrist()와 findAny()의 반환타입은 Optional<T>이며,
스트림의 요소가 없을 때는 비어있는 Optional객체를 반환한다
② 스트림의 최종 연산 - reduce()
스트림의 요소를 줄여가며 연산을 수행하고 최종 결과 반환

2-2) 스트림의 최종 연산 - collect
collect()가 스트림의 요소를 수집하려면
어떻게 수집할 것인 가에 대한방법이 정의돼야 한다.
이 방법을 정의 한 것이 컬렉터(Collector)이다.
collect() 스트림의 최종 연산. 매개변수로 컬렉터를 필요로한다.
Collector 인터페이스, 컬렉터는 이 인터페이스를 구현해야 한다.
Collectors 클래스,미리 작성된 컬렉터를 제공한다.(컬렉터를 구현한 클래스)
collect()의 매개변수 타입이 Collector인데
이는 Collector를 구현한 클래스의 객체여야 한다는 의미이다.
그리고 collect()는 이 객체에 구현된 방법대로 스트림 요소를 수집한다.
① 스트림을 컬렉션으로 변환 - toList(), toSet(), toMap(), toCollction()
② 스트림을 배열로 변환 -toArray()
Student[] stuNames = studentStream.toArray(Student[]::new); //ok.
Student[] stuNames = studentStream.toArray(); //에러
Object[] stuNames = studentStream.toArray(); //ok.
Student 스트림을 Student배열에 담으려면 매개변수가 있는 toArray()를 써야 한다.
매개변수가 없는 toArray()를 쓴다면 Object배열에 담아야 한다.
③ 스트림의 통계 - counting(), summingInt()
collect()를 사용한 통계는 그룹별로 나누어 계산하는 게 가능하다.
그냥 count의 경우 전체로 계산한다.
④ 스트림을 리듀싱 - reducing()
reduce()와 하는 일은 같다.
reducing은 그룹별 리듀싱이 가능하다.
⑤ 스트림을 문자열로 결합 - joining()
문자열 스트림의 모든 요소를 하나의 문자열로 연결하여 반환
구분자를 지정할 수 있고, 접두사/접미사를 지정할 수도 있다.
스트링의 문자열 요소가 문자열이 아닌 경우 먼저 map()을 이용해 문자열로 변환해야 한다
⑥ 스트림의 그룹화와 분할
그룹화 → 스트림의 요소를 특정 기준으로 그룹화
분할 → 스트림의 요소를 두 가지로 분할.
지정된 조건에 일치하는 그룹, 불일치하는 그룹으로 분할
groupBy() → 스트림의 요소를 Function으로
partitioningBy() → 스트림의 요소를 Predicate으로 분류한다
스트림을 두 개의 그룹으로 나눠야 한다면 partitioningBy()이 적합하다.
그리고 그룹화와 분할의 결과는 Map에 담겨서 반환된다.





'Java' 카테고리의 다른 글
java.lang패키지와 유용한 클래스 -(2) (0) | 2022.05.09 |
---|---|
Java 람다와 스트림 - (1) (0) | 2022.05.02 |
Java 쓰레드 (0) | 2022.04.29 |
Java 지네릭스, 열거형, 애너테이션 (0) | 2022.04.28 |
Java 컬렉션프레임웍 - (2) (0) | 2022.04.27 |