Reputation: 1461
I'll start by acknowledging that erasure might make this impossible. Here's what I'm trying to do, which doesn't work:
import java.util.*;
import java.util.function.*;
import java.util.stream.*;
public class Suppliers {
public static <CollectionType, T> CollectionType<T>
fill(CollectionType colltype, Supplier<T> gen, int n) {
return Stream.generate(gen)
.limit(n)
.collect(colltype::new, colltype::add, colltype::addAll);
}
}
The goal is to generate an instance of CollectionType
and fill it with n
items using gen
. This form of collect()
does instantiate a new collection but it's not clear to me whether that type can be passed through via the argument list of fill()
. The fill()
method doesn't have to look exactly this way as long as it instantiates a new collection and fills it up and returns the result.
Upvotes: 2
Views: 662
Reputation: 95316
You've got the right idea, but what you want is along the lines of:
<T, C extends Collection<T>> C fill(Supplier<T> gen,
int n,
Supplier<C> factory) {
return Stream.generate(gen)
.limit(n)
.collect(factory, C::add, C::addAll);
}
Then you can call it with:
HashSet<String> strings = fill(() -> "Foo", 10, HashSet::new);
This technique is used in methods like the 4-arg version of Collectors.toMap()
.
Upvotes: 5