Take the following line of sample code:
Set<String> someSet = someColletion.stream().map(p -> p.toString()).collect(Collectors.toSet());
I want a HashSet
. Taking a debugger to the code, I am indeed getting a HashSet
. I had a look at java.util.stream.Collectors.toSet()
to observe the following code:
public static <T> Collector<T, ?, Set<T>> toSet() { return new CollectorImpl<>((Supplier<Set<T>>) HashSet::new, Set::add, (left, right) -> { left.addAll(right); return left; }, CH_UNORDERED_ID); }
The contract guarantees a Set
, and implementation decides on a HashSet
; seems reasonable. However, my implementation needs the constant time lookup guaranteed by a HashSet
, not just any old Set
. If the implementation of toSet()
decides to use say a FooSet
, which is perfectly within its rights, my implementation is compromised.
What is the best practise solution to this problem?
Collectors toSet() returns a Collector that accumulates the input elements into a new Set. There are no guarantees on the type, mutability, serializability, or thread-safety of the Set returned.
So as long as you don't do weird things like combine function return null , the Collector always return at least a mutable container using your provided supplier function. And I think it's very counter-intuitive if an implementation would ever return null container. Show activity on this post.
Stream can be converted into Set using forEach(). Loop through all elements of the stream using forEach() method and then use set. add() to add each elements into an empty set.
Collectors is a final class that extends Object class. It provides reduction operations, such as accumulating elements into collections, summarizing elements according to various criteria, etc. Java Collectors class provides various methods to deal with elements.
If you want a guaranteed HashSet
, use Collectors.toCollection(HashSet::new)
.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With