可以将文章内容翻译成中文,广告屏蔽插件可能会导致该功能失效(如失效,请关闭广告屏蔽插件后再试):
问题:
So I have been using Guava's Optional for a while now, and I moving to Java 8 so I wanted to use it's Optional class, but it doesn't have my favorite method from Guava, asSet(). Is there a way to do this with the Java 8 Optional that I am not seeing. I love being able to treat optional as a collection so I can do this:
for( final User u : getUserOptional().asSet() ) {
return u.isPermitted(getPermissionRequired());
}
In some cases avoids the need for an additional variable.
IE
Optional<User> optUser = getUserOptional();
if ( optUser.isPresent() ) {
return optUser.get().isPermitted(getPermissionRequired());
}
Is there an easy way to replicate the Guava style in Java 8's Optional?
Thanks
回答1:
There is a simple way of converting an Optional
into a Set
. It works just like any other conversion of an Optional
:
Given an Optional<T> o
you can invoke
o.map(Collections::singleton).orElse(Collections.emptySet())
to get a Set<T>
. If you don’t like the idea of Collections.emptySet()
being called in every case you can turn it into a lazy evaluation:
o.map(Collections::singleton).orElseGet(Collections::emptySet)
however, the method is too trivial to make a performance difference. So it’s just a matter of coding style.
You can also use it to iterate like intended:
for(T t: o.map(Collections::singleton).orElse(Collections.emptySet()))
// do something with t, may include a return statement
回答2:
You appear to only be using asSet
so you can write a for loop, but that's unnecessary in Java 8. Instead of your code
Optional<User> optUser = getUserOptional();
if ( optUser.isPresent() ) {
return optUser.get().isPermitted(getPermissionRequired());
}
you could write
getUserPresent().map(optUser -> optUser.isPermitted(getPermissionRequired()))
.orElse(false);
...or, in many cases, you could use Optional.ifPresent(Consumer<T>)
.
回答3:
You can use map
:
return optUser.map(u -> u.isPermitted(getPermissionRequired()));
But it would return an Optional<WhateverTypeIsPermittedReturns>
.
Reference
public Optional map(Function mapper)
If a value is present, apply the provided mapping function to it, and
if the result is non-null, return an Optional describing the result.
Otherwise return an empty Optional.
回答4:
I also don't see a really elegant, built-in way to do this, but would like to propose a solution similar to that of Dici:
public static <T> Set<T> asSet(Optional<T> opt) {
return opt.isPresent() ?
Collections.singletonSet(opt.get()) :
Collections.emptySet();
}
This avoids the creation of a new HashSet
instance and the insertion of the optional object. (Note: This is basically the "inlined" version of what Guavas Present
and Absent
classes do: The Present
class returns the singletonSet
, and the Absent
class returns the emptySet
).
The usage would be similar to your original pattern:
for( final User u : asSet(getUserOptional()) ) {
return u.isPermitted(getPermissionRequired());
}
回答5:
You can modify your getUserOptional so that it returns a Set or implement your own asSet method :
public Set<User> getUserOptional() {
Optional<User> optUser;
//your code
Set<User> result = new HashSet<>();
if (optUser.isPresent())
result.add(optUser.get());
return result;
}
or
public static <T> Set<T> asSet(Optional<T> opt) {
Set<T> result = new HashSet<>();
if (opt.isPresent())
result.add(opt.get());
return result;
}
I don't know if there is a built-in way to do it however.