TL;DR
According to the documentation Collector Collectors.toSet()
(used in another answer) gives no guarantees on the mutability of the returned Set
. Currently, it provides a mutable general purpose implementation - HashSet
.
If you need an Immutable Set
here are the options:
There are several ways to generate an Unmodifiable Set offered by JDK.
And you can make use of the Guava's features that allow to produce ImmutableSet
including Collector
ImmutableSet.toImmutableSet()
.
Challenging the Problem-statement
Firstly, it's a discouraged practice to pass around Optional
s.
Here's quote from the answer by Brian Goetz, Java Language Architect, regurding the disign goals of Optional
:
Our intention was to provide a limited mechanism for library
method return types where there needed to be a clear way to
represent "no result", and using null for such was overwhelmingly
likely to cause errors.
For example, you probably should never use it for something that
returns an array of results, or a list of results; instead return an
empty array or list. You should almost never use it as a field of
something or a method parameter.
Also see the answer by Stuart Marks, Java and OpenJDK developer Uses for Optional.
A cleaner alternative to using Optional
as method parameter passing around the Optional
you can provide a Supplier
of Optional
and evaluate it inside your method.
Assuming you have methods foo()
and bar()
returning an Optional
, then if you change the method signature to:
getValues(Supplier<Optional<T>> first, Supplier<Optional<T>> second)
Then you can invoke the method like that: getValues(x::foo, y::bar)
And instead of operating with two optionals the problem can be generified to:
"Collect N values from non-empty Optionals into an ImmutableSet"
Since Guava release version 21.0
(which requires JDK 8 as a minimum version) you can use Collector
returned by ImmutableSet.toImmutableSet()
.
@SafeVarargs
private static <T> Set<T> getValues(Supplier<Optional<T>>... suppliers) {
return Arrays.stream(suppliers)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(ImmutableSet.toImmutableSet());
}
And just for the purpose of completeness, here's a solution with no dependencies required.
Since Java 10 Collector toUnmodifiableSet()
is available in the JDK.
@SafeVarargs
private static <T> Set<T> getValues(Supplier<Optional<T>>... suppliers) {
return Arrays.stream(suppliers)
.map(Supplier::get)
.filter(Optional::isPresent)
.map(Optional::get)
.collect(Collectors.toUnmodifiableSet());
}