user1677663
user1677663

Reputation: 1461

Java 8 Generic use of Stream.collect()

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

Answers (1)

Brian Goetz
Brian Goetz

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

Related Questions