How to peek on an Optional?

纵饮孤独 提交于 2020-01-01 07:52:29

问题


I want to use the fluent api of Optional and apply two Consumers to it.

I'm dreaming about something like this:

Optional.ofNullable(key)
    .map(Person::get)
    .ifPresent(this::printName)
    .ifPresent(this::printAddress); // not compiling, because ifPresent is void

How do I apply several Consumers to an Optional?


回答1:


Here's how you can implement the missing peek method for Optional:

<T> UnaryOperator<T> peek(Consumer<T> c) {
    return x -> {
        c.accept(x);
        return x;
    };
}

Usage:

Optional.ofNullable(key)
    .map(Person::get)
    .map(peek(this::printName))
    .map(peek(this::printAddress));



回答2:


You can use this syntax:

ofNullable(key)
    .map(Person::get)
    .map(x -> {printName(x);return x;})
    .map(x -> {printAddress(x);return x;});



回答3:


While this may not seem very elegant, I would just combine both methods into one lambda and pass that to ifPresent:

ofNullable(key)
    .map(Person::get)
    .ifPresent(x -> {printName(x); printAddress(x);});

Alternatively, you could also use andThen to chain multiple consumers, although this would require you to cast the method reference to Consumer, which is not very elegant either.

ofNullable(key)
    .map(Person::get)
    .ifPresent(((Consumer) this::printName).andThen(this::printAddress));



回答4:


With the new stream method in the Optional API as of JDK9, you can invoke the stream method to transform from Optional<T> to Stream<T> which then enables one to peek and then if you want to go back to the Optional<T> just invoke findFirst() or findAny().

an example in your case:

Optional.ofNullable(key)
        .map(Person::get) // Optional<Person>
        .stream() // Stream<Person>
        .peek(this::printName)
        .peek(this::printAddress)
        ...



回答5:


Maybe something like this:

Optional.ofNullable(key)
        .map(Person::get)
        .ifPresent(combine(this::printAddress, this::printWish));

where combine is:

public <T> Consumer<T> combine(Consumer<T>... cs) {
  return x -> Stream.of(cs).peek(c -> c.accept(x)).close();
}



回答6:


Java 8 alternative (map + orElseGet):

Optional.ofNullable(key)
        .map(Person::get) // Optional<Person>
        .map(Stream::of)  // Optional<Stream<Person>>
        .orElseGet(Stream::empty) // Stream<Person>
        .peek(this::printName)
        .peek(this::printAddress)
        .findAny();


来源:https://stackoverflow.com/questions/43737212/how-to-peek-on-an-optional

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!