Feuermurmel
Feuermurmel

Reputation: 9922

emptyList() vs emptySet(), is there any reason to chose one over the other if an instance of Collection is needed?

In the JDK, there's Collection.emtpyList() and Collection.emptySet(). Both in their own right. But sometimes all that is needed is an empty, immutable instance of Collection. To me, there's no reason to chose one over the other as both implement all operations of Collection in an efficient way and with the same results. Yet each time I need such an empty collection I ponder which one to use for a second of two.

I do not expect to gain a deeper understanding of the collections framework from an answer to this question but maybe there's a subtle reason I could use to justify choosing one over the other without thinking about it ever again.

An answer should state at least one reason preferring one of Collection.emtpyList() and Collection.emptySet() over the other in a context where they're functionally equivalent. An answer is better if the stated reason is near the top of this list:

Examples where this question arises

To give some context, here are two examples where I am in need of an empty, unmodifiable collection.

This is an example of an API that allows creating some object by optionally specifying a collection of objects that are used in the creation. The second method just calls the first one with an empty collection:

static void createObjectWithTheseThings(Collection<Thing> things) {
    ...
}

static void createObjectWithoutAnyThings() {
    createObjectWithTheseThings(Collections.emptyXXX());
}

This is an example of an Entity with state represented by an immutable collection stored in a non-final field. On initialization the field should be set to an empty collection:

class Example {
    // Initialized to an empty collection.
    private Collection<T> containedThings = Collections.emptyXXX();

    ...
}

Upvotes: 1

Views: 798

Answers (3)

Dan Getz
Dan Getz

Reputation: 9134

The only situation I can imagine this making a difference is if the code that will use your Collection does something like this:

Collection<T> collection = ...
List<T> asAList;
if (collection instanceof List) {
    asAList = (List<T>) collection;
} else {
    asAList = new ArrayList<T>(collection);
}

Obviously in a case like this you would want to use emptyList(), while if the secret target type was a Set, you'd want emptySet().

Otherwise, in terms of what "makes more sense", I agree with @ac3's logic that a generic Collection is like a Bag, and an empty immutable Set and empty immutable Bag are pretty much the same thing. However, a person very used to using immutable lists might find those easier to think of.

Upvotes: 1

ac3
ac3

Reputation: 196

Unfortunately I don't have an answer that will make the top of your priority list but if I were you I'd settle on

Collections.emptySet
  • Type inference was your first priority but I don't know if the choice can/should influence that given you were looking for an emptyCollection()

  • On the second priority, think about any api that takes in a collection which performs differently (accidentally/intentionally) based on the sub-interfaces of the concrete object passed in. Aren't they more likely to offer varied performance based on the concrete implementations (as with an ArrayList or LinkedList) instead? The empty set/list are not modeled on any empty data structures anyway; they are dummy implementations - hence no real difference

  • Based on java's modelling of these interfaces (which admittedly is not ideal), a Collection is very similar to a Set. In fact I think the methods are almost exactly the same. Logically too it looks OK with List being the specific-sub type that adds additional ordering concerns.

Now Collection and Set looking very similar(java-wise) brings up a question. If you are using a Collection type, it is clear it is not a list you want. Now the question is are you sure you don't mean a Set. If you don't, then are you using something like a Bag (surely there must be concrete instances which are not empty in the overall logic). So if you are concerned with say a Bag, then shouldn't it be up to the Bag api to provide an emptyBag() method? Just wondering. btw, I'd stick with emptySet() in the meantime :)

Upvotes: 3

Durandal
Durandal

Reputation: 20059

For the emptyXXX(), it really doesn't matter at all - since they are both empty (and they are unmodifieable, so they always stay empty) it doesn't matter at all. They will be equally suited to all operations Collection offers.

Take a look at what Collections really gives you there: Special implementations (the instances are shared across calls!). All relevant operations are dummy implementations that either return a constant result or immediately throw. Even iterator() is just a dummy with no state.

It wont make any notable difference at all.

Edit: You could say for the special case of emptyList/Set, they are semantically and complexity-wise the same at the Collecton interface level. All operations available on Collection are implemented by emptySet/List as O(1) operations. And since they're following both the contract defined by Collection, they are semantically identical too.

Upvotes: 1

Related Questions