What is the benefit for Collections.singleton() to return a Set instead of a Collection?

I'm not sure there's a "benefit" or "advantage" per se? It's just the method that returns a singleton Set, and happens to be the default implementation when you want a singleton Collection as well, since a singleton Collection happens to be a mathematical set as well.


Immutable

The benefit is found in the first adjective read in that JavaDoc documentation: immutable.

There are times when you are working with code that demands a Set (or List, etc.). In your own context you may have a strict need for only a single item. To accomplish your own goal of enforcing the rule of single-item-only while needing to present that item in a set, use a Set implementation that forbids you from adding more than one item.

“Immutable” on Collections::singleton means that, once created, the resulting Set object is guaranteed to have one, and only one item. Not zero, and not more than one. No more can be added. The one item cannot be removed.

For example, imagine your code is working with an Employee object representing the CEO (Chief Executive Officer) of your company. Your code is explicitly dealing with the CEO only, so you know there can be only one such Employee object at a time, always one CEO exactly. Yet you want to leverage some existing code that creates a report for a specified collection of Employee objects. By using Collection.singleton you are guaranteed that your own code does not mistakenly have other than one single employee, while still being able to pass a Set.

Set< Employee > ceo = Collections.singleton( new Employee( "Tim Cook" ) ) ;  // Always exactly one item in this context, only one CEO is possible.

ceo.add( … ) ;     // Fails, as the collection is immutable.
ceo.clear() ;      // Fails, as the collection is immutable.
ceo.remove( … ) ;  // Fails, as the collection is immutable.

someReport.processEmployees( ceo ) ;

Java 9: Set.of & List.of

Java 9 and later offers new interface methods Set.of and List.of to th same effect, an immutable collection of a single element.

Set< Pet > pet = Set.of( someDog ) ;

But sibling of methods are overloaded to accept any number of elements to be in the immutable collection, not just one element.

Set< Pet > pets = Set.of( someDog , someOtherDog , someCat ) ;

I wondered the same thing and came across your question in my research. Here is my conclusion:

Returning a Set keeps the Collections API clean.

Here are the methods for getting a singleton Collection:

  • public static <T> Set<T> singleton(T o)
  • public static <T> List<T> singletonList(T o)
  • public static <K,V> Map<K,V> singletonMap(K key, V value)

What if the API designers decided on having a singletonSet method and singleton method? It would look like this:

  • public static <T> Collection<T> singleton(T o)
  • public static <T> Set<T> singletonSet(T o)
  • public static <T> List<T> singletonList(T o)
  • public static <K,V> Map<K,V> singletonMap(K key, V value)

Is the singleton method really necessary? Let's think about why we would need some of these methods.

Think about when you would call singletonList? You probably have an API that requires List instead of Collection or Set. I will use this poor example:

public void needsList(List<?> list);

You can only pass a List. needsList hopefully needs the data indexed and is not arbitrarily requesting a List instead of a Collection.

However, you could also pass a List to a method that required any Collection:

public void needsAnyCollection(Collection<?> collection);

But if that is the case, then why use a List? A List has a more complicated API and involves storing indexes. Do you really need the indexes? Would a Set not suffice? I argue that you should use a Set, because needsAnyCollection does not care about the order.

This is where singletonSet really shines. You know that if the collection is of size 1 (singleton), then the data must be unique. Collections of size 1 are coincidentally a Set.

There is no need for a method which returns a singleton of type Collection, because it is accidentally a Set.