[JAVA] 람다와 스트림 ( Lambda & Stream ) ⑨

DongGyu Jung·2022년 5월 4일
0

자바(JAVA)

목록 보기
57/60
post-thumbnail

🏃‍♂️ 들어가기 앞서..

본 게시물은 스터디 활동 중에 작성한 게시물로 자바의 정석-기초편 교재를 학습하여 정리하는 글입니다.
※ 스터디 Page : 〔투 비 마스터 : 자바〕

*해당 교재의 목차 순서와 구성을 참고하여 작성하며
각 내용마다 부족할 수 있는 내용이나 개인적으로 궁금한 점은
추가적인 검색을 통해 채워나갈 예정입니다.



🧶 Optional<T>

" T타입 객체의 래퍼(Wrapper) 클래스 "로
어떠한 타입이든 모든 객체를 담을 수 있다.
java.util.Optional 은 JDK 1.8부터 추가되었다.

public final class Optional<T> {
	private final T value ; // T타입 참조변수 --> 모든 종류의 객체 저장 가능 (null 까지)
	...
}
  • null 까지 담아서 간접적으로 다룰 수 있다.

    • null을 직접 다루는 것은 NullPointerException 때문에 위험한데 이를 방지 할 수 있다.
    • 기존 null 체크를 위한 if문으로 인해 코드가 지저분해지는 것을 방지할 수 있다.

Optional<T> 객체 생성

of()

String str = "abc" ; // "abc" 값을 가진 String 객체1
Optional<String> optVal = Optional.of(str); // Optional 객체로 Wrapping 
// -> "abc"값의 주소를 참조하는 String 객체를 가진 < Optional 객체 1 >

Optional<String> optVal = Optional.of("abc");
// -> "abc"값의 String 객체를 가진 < Optional 객체 2 >

Optional<String> optVal = Optional.of(new String("abc"));
// -> "abc"값을 가진 새로운 String 객체를 가진 < Optional 객체 3 >

Wrapper 클래스이기 때문에
한 단계를 더 거쳐서 감싸는 형태인 것이다.

단, null값을 사용할 땐 of() 메서드를 사용하면 안된다.

ofNullable()

참조 변수의 값이 null일 가능성 이 있을 경우,
of() 대신 ofNullable()을 사용해야 한다.

String str = "abc" ; // "abc" 값을 가진 String 객체1
Optional<String> optVal = Optional.ofNullable(str); // Optional 객체로 Wrapping 
Optional<String> optVal = Optional.ofNullable(null);
Optional<String> optVal = Optional.of(null); // NullPointerException 발생

물론 Optional<T> 타입의 참조변수를 초기화할 때,
null이 가능하긴 하나 바람직하지 않다.

따라서
Optional<T> 타입 참조변수 초기화】 : <T>empty() 메서드 사용

  • empty()메서드는 지네릭 메서드
    하지만 추정가능하기 때문에 보통 생략할 수 있다.
Optional<String> optVal = null ; //가능은 하나 "비권장"
Optional<String> optStrVal = Optional.empty() ;
Optional<Integer> optIntVal = Optional.empty() ;
...


Optional<T> 객체 " 값 " 가져오기

get()

Optional 객체에 저장된 값을 가져올 때는 보통 get() 메서드를 잘 사용하지는 않는데

잘 쓰이지 않는 이유는
값이 null 일 때NoSuchElementException 예외가 발생하기 때문이다.

이 경우에는 아래의
orElse() 메서드로 대체해서 사용해야 한다.

orElse()

값이 null 일 때, 매개변수로 입력된 대체값 을 반환한다.

Optional<String> optVal = Optional.of("abc") ;
String str1 = optVal.get(); // str1 == "abc"
String str2 = optVal.orElse("EMPTY"); // str2 = "abc"

Optional<String> optVal = Optional.ofNullable(null) ;
String str1 = optVal.get(); // NoSuchElementException 예외
String str2 = optVal.orElse("EMPTY"); // str2 = "EMPTY"  

orElseGet()

null일 때, null을 대체할 값을 반환하는 람다식 지정

orElseThrow()

null일 때, 지정된 예외를 발생시키는 메서드

orElseGet()orElseThrow() 둘 다
orElse() 메서드를 변형한 형태로

반환값만 있는 Supplier 함수형식으로 매개변수를 받는다.

T orElseGet( Supplier<? extends T> other )
T orElseGet( Supplier<? extends T> exceptionSupplier )

Optional<String> optVal = Optional.ofNullable(null) ;
String str3 = optVal.orElseGet(String::new); // null 이면 () -> new String()과 동일하게 객체 생성
String str4 = optVal.orElseThrow(NullPointerException::new); 
// NoSuchElementException 가 아닌 NullPointerException 예외를 생성해서 던짐.


isPresent()

Optional 객체의 값이 null 이면 false
null이 아니면 true를 반환한다. ( 반환타입 : boolean )

ifPresent()

매개변수로 Cunsumer타입 반환값은 없는 람다식을 받을 수 있는데
해당 경우에는 있으면 " 람다식 실행 "
없으면 " 아무 작업도 하지 않는다 "
구조는 ifPresent( Consumer<T> block ) 인데

// isPresent() 활용
if ( Optional.ofNullable(str).isPresent() ) {// null이면 false
	System.out.println(str) ; 				// 	--> null이면 해당 코드 수행 X
}

Optional.ofNullable(str).ifPresent(System.out::println) ; // null이면 "반환 없이" 해당 코드 수행 X



🔱 OptionalInt / OptionalLong / OptionalDouble

" 기본형 타입 값의 래퍼(Wrapper) 클래스 "로
Optional<T> 보다 더 높은 성능 효율을 위해!!

실제 모습은 Optional<T> 와 크게 다를 바 없다.

public final class OptionalInt {
	private final int value ; // int 타입(기본형) 참조변수

	// 비어있는 기본값 0인지 진짜 정수값 0인지 비교하기 위해서 필요
	private final boolean isPresent ; // --> 값이 저장되어 있으면 true	
	...
}

그리고 값을 가져오는 메서드
앞선 Optional<T>의 경우는 get()이였는데

이를 단순히 응용해서

  • OptionalInt : int getAsInt()

  • OptionalLong : long getAsLong()

  • OptionalDouble : double getAsDouble()

이런 메서드를 사용한다.

그런데
아까 Optianal<T>에서는
비어있는 값/초기값/초기화 를 String 경우에서 null을 사용했지만

기본형 int의 경우,
기본값이 0이다.

"""
즉, 이렇게 된다면 진짜 값 0이 들어간 경우와,
비어있는 OptionalInt 객체를 나타내는 기본값 0은 어떻게 비교할까?

"""

다행히
OptionalInt 코드에서 본
비어있는지 확인해주기 위한 인스턴스 변수 isPresent 를 비교해
이를 구분해준다.
( 해당 변수 값이 true : 실제 값이 저장되어 있는 상태 )

0개의 댓글