Java 8 - Optional.flatmap和Optional.map之间的区别

时间:2021-08-03 19:03:50

What's the difference between these two methods: Optional.flatMap() and Optional.map()?

这两种方法有什么区别:Optional.flatMap()和Optional.map()?

An example would be appreciated.

一个例子将不胜感激。

4 个解决方案

#1


84  

Use map if the function returns the object you need or flatMap if the function returns an Optional. For example:

如果函数返回您需要的对象,则使用map;如果函数返回Optional,则使用flatMap。例如:

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 Optional<String> getOutputOpt(String input) {
  return input == null ? Optional.empty() : Optional.of("output for " + input);
}

static String getOutput(String input) {
  return input == null ? null : "output for " + input;
}

Both print statements print the same thing.

两个打印语句都打印相同的内容。

#2


36  

They both take a function from the type of the optional to something.

它们都从可选类型中获取函数。

Map applies the function "as is" on the optional you have:

Map在您拥有的可选项上应用“原样”功能:

if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));

What happens if your function is a function from T -> Optional<U>? Your result is now an Optional<Optional<U>>!

如果你的函数是来自T - > Optional 的函数,会发生什么?您的结果现在是可选 <可选 >!

That's what flatMap is about: if your function already returns an Optional, flatMap is a bit smarter and doesn't double wrap it, returning Optional<U>. It's the composition of two functional idioms: map and flatten.

这就是flatMap的意思:如果你的函数已经返回一个Optional,那么flatMap有点聪明并且没有双重包装,返回Optional 。它是两个功能成语的组成:map和flatten。

#3


4  

Note:- below is the illustration of map and flatmap function, otherwise Optional is primarily designed to be used as a return type only.

注意: - 下面是map和flatmap函数的图示,否则Optional主要设计为仅用作返回类型。

As you already may know Optional is a kind of container which may or may not contain a single object, so it can be used wherever you anticipate a null value(You may never see NPE if use Optional properly). For example if you have a method which expects a person object which may be nullable you may want to write the method something like this:

您可能已经知道Optional是一种容器,可能包含也可能不包含单个对象,因此可以在预期空值的任何地方使用它(如果正确使用Optional,您可能永远不会看到NPE)。例如,如果你有一个方法需要一个可以为空的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
}

Here you have returned a String type which is automatically wrapped in an Optional type.

在这里,您返回了一个String类型,它自动包装在Optional类型中。

If person class looked like this, i.e. phone is also Optional

如果人员班级看起来像这样,即电话也是可选的

class Person{
  private Optional<String> phone;
  //setter,getter
}

In this case invoking map function will wrap the returned value in Optional and yield something like:

在这种情况下,调用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));
}

PS; Never call get method (if you need to) on an Optional without checking it with isPresent() unless you can't live without NullPointerExceptions.

PS;永远不要在一个Optional上调用get方法(如果你需要)而不用isPresent()检查它,除非你不能没有NullPointerExceptions。

#4


1  

While already being answered someone new to Java might have not grasped this. What helped me was a look at the source code of the two functions.

虽然已经有人回答了Java新手,但可能还没有抓住这一点。帮助我的是看两个函数的源代码。

Map - wraps the result in an Optional.

Map - 将结果包装在Optional中。

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 - returns the 'raw' object

flatMap - 返回'raw'对象

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
    }
}

#1


84  

Use map if the function returns the object you need or flatMap if the function returns an Optional. For example:

如果函数返回您需要的对象,则使用map;如果函数返回Optional,则使用flatMap。例如:

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 Optional<String> getOutputOpt(String input) {
  return input == null ? Optional.empty() : Optional.of("output for " + input);
}

static String getOutput(String input) {
  return input == null ? null : "output for " + input;
}

Both print statements print the same thing.

两个打印语句都打印相同的内容。

#2


36  

They both take a function from the type of the optional to something.

它们都从可选类型中获取函数。

Map applies the function "as is" on the optional you have:

Map在您拥有的可选项上应用“原样”功能:

if (optional.isEmpty()) return Optional.empty();
else return Optional.of(f(optional.get()));

What happens if your function is a function from T -> Optional<U>? Your result is now an Optional<Optional<U>>!

如果你的函数是来自T - > Optional 的函数,会发生什么?您的结果现在是可选 <可选 >!

That's what flatMap is about: if your function already returns an Optional, flatMap is a bit smarter and doesn't double wrap it, returning Optional<U>. It's the composition of two functional idioms: map and flatten.

这就是flatMap的意思:如果你的函数已经返回一个Optional,那么flatMap有点聪明并且没有双重包装,返回Optional 。它是两个功能成语的组成:map和flatten。

#3


4  

Note:- below is the illustration of map and flatmap function, otherwise Optional is primarily designed to be used as a return type only.

注意: - 下面是map和flatmap函数的图示,否则Optional主要设计为仅用作返回类型。

As you already may know Optional is a kind of container which may or may not contain a single object, so it can be used wherever you anticipate a null value(You may never see NPE if use Optional properly). For example if you have a method which expects a person object which may be nullable you may want to write the method something like this:

您可能已经知道Optional是一种容器,可能包含也可能不包含单个对象,因此可以在预期空值的任何地方使用它(如果正确使用Optional,您可能永远不会看到NPE)。例如,如果你有一个方法需要一个可以为空的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
}

Here you have returned a String type which is automatically wrapped in an Optional type.

在这里,您返回了一个String类型,它自动包装在Optional类型中。

If person class looked like this, i.e. phone is also Optional

如果人员班级看起来像这样,即电话也是可选的

class Person{
  private Optional<String> phone;
  //setter,getter
}

In this case invoking map function will wrap the returned value in Optional and yield something like:

在这种情况下,调用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));
}

PS; Never call get method (if you need to) on an Optional without checking it with isPresent() unless you can't live without NullPointerExceptions.

PS;永远不要在一个Optional上调用get方法(如果你需要)而不用isPresent()检查它,除非你不能没有NullPointerExceptions。

#4


1  

While already being answered someone new to Java might have not grasped this. What helped me was a look at the source code of the two functions.

虽然已经有人回答了Java新手,但可能还没有抓住这一点。帮助我的是看两个函数的源代码。

Map - wraps the result in an Optional.

Map - 将结果包装在Optional中。

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 - returns the 'raw' object

flatMap - 返回'raw'对象

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
    }
}