백엔드/Java의 정석

TIL 정리_28

ran4 2022. 3. 15. 23:48

 

Optional<T>와 OptionalInt // java.util.Optional (JDK 1.8)

 

Optonal<T>는 지네릭 클래스로 T타입의 객체를 감싸는 래퍼클래스이다 

**래퍼(wrapper)클래스 : 객체가 아닌 8개의 기본형을 객체로 다뤄야할 때 사용하는 클래스

->Optional타입의 객체에는 모든 타입의 참조변수를 담을 수 있다

public final class Optional<T> {
private final T value; // T타입의 참조변수
--- }

최종연산의 결과를 Optional 객체에 담아서 반환한다

->반환된 결과가 null인지 if문으로 체크하는 대신 Optional에 정의된 메서드를 통해 간단히 처리가능

 

Optional 객체 생성

of() 또는 ofNullable()을 사용한다 //ofNullable() - 참조변수의 값이 null일 가능성이 있을때

Optional<String> optVal = Optional.of(str);

Optional<String> optVal = Optional.ofNullable(null);

참조변수를 기본값으로 초기화 empty()

Optional<String> optVal = Optional.<String>empty();

 

Optional객체의 값 가져오기 

get() : Optional 객체에 저장된 값을 가져온다

orElse() : 값이 null일 때 대체할 값을 지정한다

->orElseGet() : 대체할 값을 반환하는 람다식 지정 orElseThrow() : 지정된 예외를 발생

isPresent() : Optional 객체의 값이 null이면 false, 아니면 true 반환한다

 

OptionalInt, OptionalLong, OptionalDouble //성능이 더 좋다

IntStream같은 기본형 스트림에는 Optional도 기본형을 값으로 반환한다(래퍼클래스)

Optional 클래스 값을 반환하는 메서드
Optional<T> T get()
OptionalInt int getAsInt()
OptionalLong long ageAsLong()
OptionalDouble double getAsDouble()

 

스트림의 최종 연산

스트림의 요소를 소모해서 결과를 만들어낸다 ->이후 연산 불가

 

-forEach()

스트림의 모든 요소에 지정된 작업을 수행한다 –> forEach(), forEachOrdered()

반환타입이 void이며 스트림의 요소를 출력하는 용도로 많이 사용된다

void forEach(Consumer<? super T> action) //병렬 스트림일 때 순서보장 x

void forEachOrdered(Consumer<? super T> action)) //병렬 스트림인 경우에도 순서보장

*병렬 스트림 : 작업을 병렬로 처리한다 

 

조건검사 -allMatch(), anyMatch(), noneMatch(), findFirst(), findAny()

모든 요소가 일치하는지. 일부가 일치하는지, 어떤 요소도 일치하지 않는지 확인할 때 사용한다

매개변수로 Predicate를 요구하며, 연산결과를 boolean으로 반환한다

boolean allMatch (Predicate<? super T> predicate) //모든 요소가 조건을 만족할 때 true

boolean anyMatch (Predicate<? super T> predicate) //한 요소라도 만족할 때 true

boolean noneMatch (Predicate<? super T> predicate) //모든요소가 불만족할 때 true

 

조건에 일치하는 요소 찾기 findFirst(), findAny()

Optional<T> findFirst() //첫 번째 요소를 반환. 순차 스트림에 사용

Optional<T> findAny() //아무거나 하나를 반환. 병렬 스트림에 사용

 

통계 - count(), sum(), average(), max(), min()

기본형 스트림의 스트림 요소들에 대한 통계정보를 제공하는 메서드

기본형 스트림이 아닌경우에는 아래의 메서드를 사용한다

long count()

Optional<T> max()

Optional<T> min()

=>대부분은 위의 메서드를 사용하지 않고 기본형 스트림으로 변환하거나

reduce(), collect()를 사용해서 통계정도를 얻는다 

 

리듀싱 - reduce()

스트림의 요소를 줄여나가면서 연산을 수행하고 최종결과를 반환한다

->매개변수의 타입이 BinaryOperator<T> 

초기값과 어떤 연산으로 스트림의 요소를 줄여나갈 것인지 결정하고 사용한다

 

identity 초기값

accumulator 이전 연산결과와 스트림의 요소에 수행할 연산

combiner 병렬처리된 결과를 합치는데 사용할 연산(병렬 스트림)

 

collect()

collect()Collector를 매개변수로 하고 스트림의 요소를 수집하는 최종연산이다

collect() : 스트림의 최종연산, 매개변수로 컬렉터를 필요로 한다
Collector : 인터페이스, 컬렉터는 이 인터페이스를 구현해야 한다
Collectors : 클래스, static 메서드로 미리 작성된 컬렉터를 제공한다 

 

스트림을 컬렉션과 배열로 변환 

-컬렉션으로 변환 toList(), toSet(), toMap(), toCollection()

스트림의 모든 요소를 컬렉션에 수집하려면  Collector클래스의 메서드를 사용해야한다

특정 컬렉션을 지정하려면 toCollection()에 해당 컬렉션의 생성자 참조를 매개변수로 넣어야 한다

 

-스트림을 배열로 변환 toArray()

스트림에 저장된 요소들을 T[]타입의 배열로 변환한다

해당 타입의 생성자 참조를 매개변수로 지정해야 한다 //지정 x -> 반환되는 배열의 타입 = Object[]

 

통계 - counting(), summingInt(), averagingInt(), maxBy(), minBy()

스트림의 통계정보를 제공한다

**스트림의 통계 : counting(), summingInt()

 

스트림을 리듀싱 - reducing() //Collectors가 제공

reduce(Integer::max); //전체 리듀싱

boxed().collect(reducing(Integer::max)); //그룹별 리듀싱

 

문자열 결합 - joining()

문자열 스트림의 모든 요소를 하나의 문자열로 연결해서 반환한다

스트림의 요소가 문자열이 아닌 경우 map()을 먼저 이용해서 변환해야 한다

->map()없이 스트림에 바로 joining()하면 스트림의 요소에 toString()을 호출한 결화를 결합한다

 

그룹화와 분할

-groupingBy()

스트림의 요소를 그룹화 스트림을 n분할한다

Function으로 분류한다

 

-partitioningBy()

스트림을 2분할한다

Predicate로 분류한다

 

=> 그룹화와 분할의 결과는 Map()에 담겨 반환된다

 

partitioningBy()에 의한 분류

학생들을 성별로 나누어 List에 담는 예시 

Map<Boolean, List<Student>> stuBySex = stuStream

.collect(partitioningBy(Student::isMale));

List<Student> maleStudent = stuBysex.get(true);

List<Student> femaleStudent = stuBySex.get(false);

 

groupingBy()에 의한 분류

stuStream을 반 별로 그룹지어 Map에 저장하는 방식

Map<Integer, List<Student>> stuByBan = stuStream

.collect(groupingBy(Student::getBan)); //to List 생략

-> groupingBy로 그룹화하면 기본적으로 List<T>에 담기때문에 생략

 

Collector 구현

반환타입이 함수형 인터페이스 //람다식 작성 

supplier() : 작업 결과를 저장할 공간을 제공

accumulator() : 스트림의 요소를 수집(collect)할 방법을 제공

combiner() : 두 저장공간을 병합할 방법을 제공(병렬 스트림)

finisher() : 결과를 최종적으로 변환할 방법을 제공

 

함수형 인터페이스가 아닌 메서드

characteristics() : 컬렉터가 수행하는 작업의 속성에 대한 정보를 제공하기 위한 것

Characteristics.CONCURRENT 병렬로 처리할 수 있는 작업

Characteristics.UNORDERED 스트림의 요소의 순서가 유지될 필요가 없는 작업

Characteristics.IDENTITY_FINISH finisher()가 항등 함수인 작업

해당하는것을 set()에 담아서 반환

 

Collector도 내부적으로 처리하는 과정이 리듀싱과 같다

 

reduce()와 collect()의 차이

근본적으로 하는 일은 같다 //reduce()에 대해 잘 이해하는게 좋다

collect() : 그룹화와 분할, 집계등에 유용하게 쓰이며 병렬화에 있어서 reduce()보다 유리하다

 

 

'백엔드 > Java의 정석' 카테고리의 다른 글

TIL 정리_30  (0) 2022.03.17
TIL 정리_29  (0) 2022.03.16
TIL 정리_27  (0) 2022.03.14
TIL 정리_26  (0) 2022.03.13
TIL 정리_25  (0) 2022.03.12