Java 8 - 옵션 간의 차이.플랫맵 및 옵션.map
이 두 방법의 차이점은 무엇인가?Optional.flatMap()
그리고Optional.map()
?
예를 들어주면 고맙겠다.
사용하다map
함수가 필요한 개체를 반환하는 경우 또는flatMap
함수가 a를 반환할 경우Optional
. 예:
public static void main(String[] args) {
Optional<String> s = Optional.of("input");
System.out.println(s.map(Test::getOutput));
System.out.println(s.flatMap(Test::getOutputOpt));
}
static String getOutput(String input) {
return input == null ? null : "output for " + input;
}
static Optional<String> getOutputOpt(String input) {
return input == null ? Optional.empty() : Optional.of("output for " + input);
}
두 인쇄물 모두 같은 것을 인쇄한다.
둘 다 선택형에서 무언가로 기능을 취한다.
map()
다음 옵션에서 "있는 그대로" 기능을 적용하십시오.
if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));
만약 당신의 기능이 다음의 함수라면 어떻게 될까?T -> Optional<U>
?
당신의 결과는 지금 입니다.Optional<Optional<U>>
!
바로 그런 것이다.flatMap()
에 대한 정보: 함수가 이미 다음 값을 반환한 경우Optional
,flatMap()
좀 더 똑똑하고 이중으로 포장하지 않고, 다시 돌아온다.Optional<U>
.
그것은 두 가지 기능 숙어들의 구성이다.map
그리고flatten
.
좋아. 중첩된 옵션과 마주할 때만 'flatMap'을 사용하면 돼.여기 그 예가 있다.
public class Person {
private Optional<Car> optionalCar;
public Optional<Car> getOptionalCar() {
return optionalCar;
}
}
public class Car {
private Optional<Insurance> optionalInsurance;
public Optional<Insurance> getOptionalInsurance() {
return optionalInsurance;
}
}
public class Insurance {
private String name;
public String getName() {
return name;
}
}
public class Test {
// map cannot deal with nested Optionals
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.map(Car::getOptionalInsurance) // ① leads to a Optional<Optional<Insurance>
.map(Insurance::getName); // ②
}
}
스트림과 마찬가지로 옵션#map은 옵션으로 포장된 값을 반환한다.그래서 중첩된 옵션 --Optional<Optional<Insurance>
. 그리고 ②에서는 보험사 인스턴스로 맵핑을 하고 싶은데, 그렇게 해서 비극이 일어난 겁니다.루트는 중첩된 옵션이다.껍데기와 상관없이 핵심 가치를 얻을 수 있다면 우리는 해낼 수 있을 것이다.그것이 플랫맵이 하는 일이다.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
결국, 나는 네가 자바8을 체계적으로 공부하고 싶다면 너에게 자바8 인 액션을 추천했다.
참고:- 아래는 지도와 플랫맵 기능에 대한 그림이며, 그렇지 않은 경우 옵션이란 주로 반환 유형으로만 사용하도록 설계되어 있다.
이미 알고 있는 바와 같이, 옵션이란 하나의 물체를 포함하거나 포함하지 않을 수 있는 용기의 일종이므로, null 값을 예상하는 곳이라면 어디에서나 사용할 수 있다(선택을 적절하게 사용하면 NPE를 볼 수 없다).예를 들어, 무효가 될 수 있는 대상에게 예상하는 방법이 있는 경우 다음과 같은 방법으로 작성하기를 원할 수 있다.
void doSome(Optional<Person> person){
/*and here you want to retrieve some property phone out of person
you may write something like this:
*/
Optional<String> phone = person.map((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
class Person{
private String phone;
//setter, getters
}
선택적 유형으로 자동 포장되는 문자열 유형을 반환하셨습니다.
만약 Person class가 이렇게 생겼다면, 즉 전화도 선택사항이다.
class Person{
private Optional<String> phone;
//setter,getter
}
이 경우 지도 함수를 호출하면 Option(옵션)으로 반환된 값이 포장되어 다음과 같은 결과를 얻을 수 있다.
Optional<Optional<String>>
//And you may want Optional<String> instead, here comes flatMap
void doSome(Optional<Person> person){
Optional<String> phone = person.flatMap((p)->p.getPhone());
phone.ifPresent((ph)->dial(ph));
}
PS; NullPointer 없이 살 수 없는 경우를 제외하고 옵션에서 (필요한 경우)가 있는 상태인지 확인하지 않고 전화 걸기 메서드(필요한 경우)를 호출하지 마십시오.예외.
나에게 도움이 된 것은 두 기능의 소스 코드를 살펴본 것이었다.
지도 - 결과를 선택사항으로 줄 바꿈.
public<U> Optional<U> map(Function<? super T, ? extends U> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Optional.ofNullable(mapper.apply(value)); //<--- wraps in an optional
}
}
플랫맵 - '원시' 개체 반환
public<U> Optional<U> flatMap(Function<? super T, Optional<U>> mapper) {
Objects.requireNonNull(mapper);
if (!isPresent())
return empty();
else {
return Objects.requireNonNull(mapper.apply(value)); //<--- returns 'raw' object
}
}
Optional.map()
:
모든 요소를 가져가고 값이 존재하는 경우 다음 함수에 전달된다.
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
Now added에는 다음 세 가지 값 중 하나가 있다.true
또는false
의 옵션으로 포장된 경우.optionalValue
존재하거나 비어 있는 선택사항.
결과를 처리할 필요가 없는 경우 간단히 사용할 수 있다.ifPresent()
반환 값:
optionalValue.ifPresent(results::add);
Optional.flatMap()
:
동일한 스트림 방법과 유사한 작업.냇물의 흐름을 평탄하게 하다.값이 제시되면 기능에 적용된다는 차이점을 가지고.그렇지 않으면 빈 선택사항이 반환된다.
선택적 가치 함수 호출을 구성하는 데 사용할 수 있다.
다음과 같은 방법이 있다고 가정해 보십시오.
public static Optional<Double> inverse(Double x) {
return x == 0 ? Optional.empty() : Optional.of(1 / x);
}
public static Optional<Double> squareRoot(Double x) {
return x < 0 ? Optional.empty() : Optional.of(Math.sqrt(x));
}
그러면 다음과 같은 역의 제곱근을 계산할 수 있다.
Optional<Double> result = inverse(-4.0).flatMap(MyMath::squareRoot);
또는, 다음을 원하는 경우:
Optional<Double> result = Optional.of(-4.0).flatMap(MyMath::inverse).flatMap(MyMath::squareRoot);
다음 중 하나라도inverse()
또는 그squareRoot()
돌아온다Optional.empty()
, 결과는 공허하다.
자세한 내용은 아래 링크를 참조하십시오(내가 찾을 수 있는 가장 좋은 설명).
https://www.programmergirl.com/java-8-map-flatmap-difference/
지도와 플랫맵 모두 - 기능 수용지도 반환 유형()은 단일 값인 반면 플랫맵은 값의 스트림을 반환함
<R> Stream<R> map(Function<? super T, ? extends R> mapper)
<R> Stream<R> flatMap(Function<? super T, ? extends Stream<? extends R>> mapper)
그들은 같은 일을 한다.
유일한 차이점은, 바로 그 점이라는 것이다.lambda
귀국의 활자는 에 의해 포장된다.Optional
그렇지 않으면.
정상적인 사용의 경우,map
flatMap
예:
package bj;
import java.util.Optional;
import static java.lang.System.out;
public class App {
public static void main(String[] args) {
out.println(Optional.of(10).map (x -> x * x));
out.println(Optional.of(10).flatMap(x -> Optional.of(x * x)));
out.println(Optional.of(10).map (x -> Optional.of(x * x).get()));
out.println(Optional.<Integer>empty().map (x -> x * x));
out.println(Optional.<Integer>empty().flatMap(x -> Optional.of(x * x)));
out.println(Optional.<Integer>empty().map (x -> Optional.of(x * x).get()));
}
}
출력:
Optional[100]
Optional[100]
Optional[100]
Optional.empty
Optional.empty
Optional.empty
'programing' 카테고리의 다른 글
무엇이 더 효율적인가?가루를 이용해 네모나게 만들거나, 아니면 그냥 곱해서 만들거나? (0) | 2022.05.14 |
---|---|
순수 C에 RAII를 구현하시겠습니까? (0) | 2022.05.14 |
C/C++ 컴파일러에 대한 최적의 컴파일러 경고 수준? (0) | 2022.05.13 |
힙 메모리(malloc/new)를 사용하면 비결정론적 프로그램이 생성되는가? (0) | 2022.05.13 |
윈도우즈에서 https를 사용하여 Vue-cli 프로젝트를 실행하는 방법 (0) | 2022.05.13 |