在Optional中包装对象以使用ifPresent方法?

时间:2018-11-07 20:34:00

标签: java optional

我正在学习可选课程。我只是对方法Optional.ifPresent(Consumer<? super T> consumer)的正确使用感到困惑。

我在一个项目上看到了这个例子:

Optional.ofNullable(user.getIdentifiantAAA())
.ifPresent(id -> identifiants.add(new Identifiant(id, IdentifiantType.AAA));

恕我直言,它的可读性不如:

if (user.getIdentifiantAAA() != null) {
   identifiants.add(user.getIdentifiantAAA());
}

The class Optional is:

  

可能包含也可能不包含非null值的容器对象。如果一个   值存在,isPresent()将返回true,get()将返回   值。

我觉得示例的Optional.ifPresent的使用破坏了该类的主要提议。仅使用isPresent方法创建Optional的实例,在这种情况下是否真的必要?

所以,我的问题是:应该将对象包装在Optional中,以使非null终止并使用方法Optional.ifPresent(Consumer<? super T> consumer)执行代码吗?

5 个答案:

答案 0 :(得分:2)

Optional<T>并不意味着可以代替简单的if检查,第一个示例肯定不是 not 创建Optional<T>的原因。

仅当您执行以下扩展逻辑时,才使用ifPresent

Optional.ofNullable(user.getIdentifiantAAA())
        .map(...)
        .ifPresent(...);

或者如果您正在使用的值已经是Optional<T>,则可能是方法调用或某些计算返回的Optional<T>

答案 1 :(得分:2)

Optional the mother of all bike sheds的@Devoxx US演讲中,Oracle的Stuart Marks详细介绍了可选的有用方式(以及有关可选的其他方面)

有用的主要用例是退货,就像@Paul Rooney提到的那样

答案 2 :(得分:1)

我敢说方法Consumer所采用的ifPresent没有要求。我个人认为这行没错:

.ifPresent(id -> identifiants.add(new Identifiant(id, IdentifiantType.AAA));

这里的问题是将user.getIdentifiantAAA()包裹在Optional中只是为了使用其方法,这是一种不良做法,并且与this thread有关。

答案 3 :(得分:0)

不确定使用它的方法是否错误,但是我经常使用的一种方法是使用功能接口。

考虑以下代码:

#include <cstdint>
#include <iostream>
#include <random>
#include <vector>
#include <numeric>
#include <cmath>

#define func auto


func nCk(uint64_t n, uint64_t k) -> double { // computes binomial coefficient
    if (k > n)
        return 0.0;

    if (k * 2ULL > n)
        k = n - k;

    if (k == 0.0)
        return 1.0;

    return exp(lgamma(n+1) - (lgamma(k+1) + lgamma(n-k+1)));
}


func PMF(uint64_t N, uint64_t K, uint64_t n, uint64_t k) -> double { // Hypergeometric distribution PMF
    return nCk(K, k) * nCk(N - K, n - k) / nCk(N, n);
}


func sample_hyper(int N, int K, int n,            // sampling from Hypergeometric distribution
                  std::mt19937_64&  rng,
                  std::vector<int>& nums) -> int {

    int rc{ 0 };
    for (int k = 0; k != n; ++k) {
        std::uniform_int_distribution<int> uni{ k, N-1 };
        auto s = uni(rng);
        std::swap(nums[k], nums[s]);

        rc += (nums[k] < K);
    }
    return rc;
}


func main() -> int {
    auto rng = std::mt19937_64{1234567891ULL};

    int N = 500; // compare with Wiki
    int K = 50;
    int n = 100;

    auto nums = std::vector<int>( N );
    std::iota(nums.begin(), nums.end(), 0); // array to shuffle, filled with 0, 1, 2, 3 ... sequence

    auto h = std::vector<int>( K, 0 ); // histogram

    int NT = 100000; // number of trials
    for(int k = 0; k != NT; ++k) {
        int q = sample_hyper(N, K, n, rng, nums);
        h[q] += 1; // count it
    }

    for (int k = 0; k != 20; ++k) { // and print it
        double e = double(h[k]) / double(NT);
        std::cout << k << "   " << e << "     " << PMF(N, K, n, k) << '\n';
    }

    return 0;
}

使用“可选”,我可以使它更简洁:

java -agentpath:/opt/cprof/profiler_java_agent.so=-cprof_service=myApp -jar myApp.jar -agentpath:/opt/cdbg/cdbg_java_agent.so=--cdbg_extra_class_path=/mydirtoclassdirectory

答案 4 :(得分:-1)

这实际上取决于偏好。 0: displayName: "XXXXXXXXXXXXXXXX" email: "XXXXXXXXXXXXXXXX" phoneNumber: null photoURL: "XXXXXXXXXXXXXXXX" providerId: "google.com" uid: "XXXXXXXXXXXXXXXX" 的全部要点是像在Optional中一样处理null