무엇 이러한 두 가지 방법의 차이는 다음과 같습니다 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 을 추천했습니다.