How to create a generic method that populates and returns an existing or a new Collection?

Viewed 61

I'm currently developing a storage library which lets the user persist objects to external storage. I wanted to add support for lists and sets so I added functions like this:

public <E extends Persistable> List<E> readList(String fileName, List<E> defaultValue)
public <E extends Persistable> Set<E> readSet(String fileName, Set<E> defaultValue)

Now I thought that it would be nice to add support for every type of Collection. I thought about something like this:

public <C extends Collection<E>, E extends Persistable> C readCollection(String fileName, C defaultValue)

My problem is the following: If the user calls readCollection(FILE, collection) and passes a non null collection as second parameter, I can use it to add the stored items to that collection. But if the user has stored items before and passes null as second parameter I have to create a new instance of the collection. Is that even possible in Java?

1 Answers

Instead of passing a default Collection instance, you can pass a Supplier<C>:

public <C extends Collection<E>, E extends Persistable> C readCollection(String fileName, Supplier<C> supplier)
{
    C collection = supplier.get();
    ...
    return collection;
}

Now you can use the Supplier<C> to create an instance of the Collection.

You'll can call that method with:

readCollection(name, ArrayList::new)

or:

readCollection(name, HashSet::new)

If you still need the functionality of adding elements to an existing Collection instance, you can create two methods - readCollection and readNewCollection.

As an alternative, you can keep your single C readCollection(String fileName, C defaultValue) method, and decide which instance to create when null is passed as the second argument. For example, you can decide the default type is ArrayList.

BTW, you would have the same problem even if you kept the original two methods - readList and readSet - since readSet can return any Set implementation, so if the second argument is null, it will have to decide which Set implementation to use.

Related