무엇 이러한 두 가지 방법의 차이는 다음과 같습니다 Optional.flatMap()
과 Optional.map()
?
예를 들어 주시면 감사하겠습니다.
무엇 이러한 두 가지 방법의 차이는 다음과 같습니다 Optional.flatMap()
과 Optional.map()
?
예를 들어 주시면 감사하겠습니다.
Stream#flatMap
와 Optional#flatMap
.
답변:
사용 map
하는 기능은 당신이 필요로하는 개체 또는 반환하는 경우 flatMap
함수가 반환하는 경우를 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);
}
두 print 문은 모두 같은 것을 인쇄합니다.
[flat]Map
매핑 함수를 input == null
? 내 이해는 그것이 Optional
없으면 sortcuts-[JavaDoc] ( docs.oracle.com/javase/8/docs/api/java/util/… )이 이것을 백업하는 것 같습니다- " 값이 있으면 적용 .. . ".
Optional.of(null)
는 Exception
. Optional.ofNullable(null) == Optional.empty()
.
둘 다 옵션 유형에서 무언가로 기능을 취합니다.
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
.
참고 :-아래는 map 및 flatmap 함수의 그림입니다. 그렇지 않으면 Optional은 주로 반환 유형으로 만 사용하도록 설계되었습니다.
이미 알고 있듯이 Optional은 단일 객체를 포함 할 수도 있고 포함하지 않을 수도있는 일종의 컨테이너이므로 null 값을 예상 할 때마다 사용할 수 있습니다 (Optional을 올바르게 사용하면 NPE가 표시되지 않을 수 있음). 예를 들어 nullable이 될 수있는 person 객체를 예상하는 메소드가있는 경우 다음과 같이 메소드를 작성할 수 있습니다.
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
}
여기서는 Optional 유형에 자동으로 래핑되는 String 유형을 반환했습니다.
사람 클래스가 이렇다면 전화도 선택 사항입니다.
class Person{
private Optional<String> phone;
//setter,getter
}
이 경우 map 함수를 호출하면 반환 된 값을 Optional로 래핑하고 다음과 같은 결과를 얻을 수 있습니다.
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));
}
추신; NullPointerExceptions없이 살 수없는 경우가 아니면 isPresent ()로 확인하지 않고 Optional에서 get 메서드를 호출하지 마십시오 (필요한 경우).
Person
이 오용 하기 때문에 당신의 대답의 본질에서 산만해질 가능성이 있다고 생각합니다 Optional
. Optional
이와 같은 회원 에게 사용 하는 것은 API의 의도에 위배됩니다-mail.openjdk.java.net/pipermail/jdk8-dev/2013-September/…
저에게 도움이 된 것은 두 기능의 소스 코드를 살펴 보는 것이 었습니다.
맵 -결과를 옵션으로 래핑합니다.
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
}
}
flatMap- '원시'객체를 반환합니다.
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
}
}
flatMap
" '원시'개체를 반환한다"는 의미는 무엇입니까 ? flatMap
또한에서 "래핑 된"매핑 된 개체를 반환합니다 Optional
. 차이점은의 경우이다 flatMap
, 매퍼 함수에 매핑 된 객체를 포함 Optional
하면서 map
자체의 객체를 포함 Optional
.
Optional.map()
:모든 요소를 취하고 값이 존재하면 함수에 전달됩니다.
Optional<T> optionalValue = ...;
Optional<Boolean> added = optionalValue.map(results::add);
이제 추가 된 값은 세 가지 값 중 하나입니다. true
또는 존재하는 경우 Optional로 , 그렇지 않으면 빈 Optionalfalse
로 래핑됩니다 .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()
, 결과는 비어 있습니다.
Optional<Double>
반환 유형으로 유형 이 있기 때문 입니다.
괜찮아. 당신은 당신이 중첩 된 선택적 개체에 직면 할 때 만 사용 '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); // ②
}
}
Stream과 마찬가지로 Optional # map은 Optional로 래핑 된 값을 반환합니다. 그래서 우리는 중첩 된 Optional- Optional<Optional<Insurance>
. 그리고 ②에서 우리는 그것을 보험 인스턴스로 매핑하고 싶습니다. 그것이 비극이 일어난 방법입니다. 루트는 중첩 된 옵션입니다. 셸에 관계없이 핵심 가치를 얻을 수 있다면 해낼 것입니다. 그것이 flatMap이하는 일입니다.
public Optional<String> getCarInsuranceName(Person person) {
return person.getOptionalCar()
.flatMap(Car::getOptionalInsurance)
.map(Insurance::getName);
}
결국 Java8을 체계적으로 공부하고 싶다면 Java 8 In Action 을 추천했습니다.