34

While going through the EnumSet<E> of method, I have seen multiple overloaded implementations of of method:

public static <E extends Enum<E>> EnumSet<E> of(E e)

public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2)

.
.

public static <E extends Enum<E>> EnumSet<E> of(E e1, E e2, E e3, E e4, E e5)

and then another overloaded method with varargs

public static <E extends Enum<E>> EnumSet<E> of(E first, E... rest) {
    EnumSet<E> result = noneOf(first.getDeclaringClass());
    result.add(first);
    for (E e : rest)
        result.add(e);
    return result;
}

When this varargs could have handled the other implementations, why this method is overloaded this way? Is there any specific reason for this?

I had gone through the Javadoc of the same, but I could not find any convincing explanation.

Somnath Musib
  • 3,548
  • 3
  • 34
  • 47
  • 2
    It looks like it's just optimized for speed. – NeplatnyUdaj Aug 10 '15 at 16:11
  • 2
    Optimization to for a bit set like EnumSet to regain something as an enum is very basic, but in java enum is not merely a named number, – Joop Eggen Aug 10 '15 at 16:18
  • 4
    Could *nearly* be considered as a duplicate of http://stackoverflow.com/questions/3737882/why-does-guavas-immutablelist-have-so-many-overloaded-of-methods?rq=1 ... – Marco13 Aug 10 '15 at 17:40

4 Answers4

29

Varargs methods create an array.

public static void foo(Object... args) {
  System.out.println(args.length);
}

This works, because of the implicit array creation. EnumSet is a class designed to be very, very fast, so by creating all the extra overloads they can skip the array creation step in the first few cases. This is especially true since in many cases Enum don't have that many elements, and if they do, the EnumSet might not contain all of them.

Javadoc for EnumSet<E> of(E e1, E e2, E e3, E e4, E e5):

Creates an enum set initially containing the specified elements. Overloadings of this method exist to initialize an enum set with one through five elements. A sixth overloading is provided that uses the varargs feature. This overloading may be used to create an enum set initially containing an arbitrary number of elements, but is likely to run slower than the overloadings that do not use varargs.

Community
  • 1
  • 1
durron597
  • 31,968
  • 17
  • 99
  • 158
8

varags creates an array, that is when we call

void x(int...x) {...}
..
x(1);

Compiler replaces last line with this:

x(new int[] {1});

It will not happen if we have an overloaded method with 1 arg:

void x(int...x) {...}
void x(int x) {...}

Then compiler will choose the second method.

Unihedron
  • 10,902
  • 13
  • 62
  • 72
Evgeniy Dorofeev
  • 133,369
  • 30
  • 199
  • 275
7

Because that class was designed by Josh Bloch, and that guy knows how things work. :) Besides creating an array, the varargs method contains the loop, which is more work for the JIT to optimize the code.

For example, if we look at the implementation of the overloaded version with five parameters:

result.add(e1);
result.add(e2);
result.add(e3);
result.add(e4);
result.add(e5);

we notice that it is some kind of an already unrolled loop that could look like:

for (E e : Arrays.asList(e1, e2, e3, e4, e5)) {
   result.add(e);
}

Also, shorter and simpler methods are more likely to be inlined than longer and more complex ones.

Dragan Bozanovic
  • 23,102
  • 5
  • 43
  • 110
6

From the javadoc:

Overloadings of this method exist to initialize an enum set with one through five elements. A sixth overloading is provided that uses the varargs feature. This overloading may be used to create an enum set initially containing an arbitrary number of elements, but is likely to run slower than the overloadings that do not use varargs.