Minborg

Minborg
Minborg

Monday, December 19, 2016

Day 19, Java Holiday Calendar 2016, Speed up Your Enums


Day 19, Java Holiday Calendar 2016, Speed up Your Enums



Today's tips is about Enum performance. A large number of Java programmers think Enums have a very fast method called .values() that returns all the Enums. Heck, it is even an array being returned so it should really be super fast? Well, not really...

Suppose we have declared an enum like this:

public enum Car {

    TESLA, VOLVO, TOYOTA;

}

then it turns out Java will generate an equivalent to the following under the hood:

    public static Car[] values() {
        return (Car[])$VALUES.clone();
    }

This means each time we are calling values(), we are creating a copy of the internal VALUES array. The reason for this is that an array cannot be protected from being overwritten by user code. Thus, a new copy must be provided for each call to guarantee state integrity. The JVM can mitigate the problem under certain circumstances but if we want to be absolutely sure no objects are created, we must implement our own equivalent to values(). This can be done like this:

public enum Car {
    TESLA, VOLVO, TOYOTA;

    private static final List<Car> VALUE_LIST = Stream.of(values())
            .collect(collectingAndThen(toList(), Collections::unmodifiableList));

    public static List<Car> valuesAsList() {
        return VALUE_LIST;
    }

}

Note that the internal VALUE_LIST is unmodifiable and that this is important, or else we cannot expose it directly via the valuesAsList() method.

Now we can use our modified Enum like this with no performance overhead :

Car.valuesAsList().forEach(System.out::println);

Follow the Java Holiday Calendar 2016 with small tips and tricks all the way through the winter holiday season. I am contributing to open-source Speedment, a stream based ORM tool and runtime. Please check it out on GitHub.

No comments:

Post a Comment