Back to Blog
Java

java enum values: Iterating Over All Constants

Learn how java enum values() works, how to iterate over enum constants, and when to cache the result for performance.

JavaEnumvalues()Iteration
An illustration showing a Java enum as colored blocks and an arrow pointing to an array of the same blocks, representing the values() method returning an array of constants.

java enum values requires a clear understanding of the core syntax, runtime behavior, and practical implementation patterns demonstrated in the examples below.

The values() method on Java enums is the simplest way to access all constants of an enum type. It returns an array of the enum constants in the order they are declared. This method is implicitly added by the compiler to every enum type, so you don't see it in the source but you can call it directly. For example, given an enum Color, you can get all colors with Color.values().

What values() Returns and How It Behaves

values() is a static method that returns an array of the enum constants. The array's length matches the number of constants, and the elements are in declaration order. Each call to values() creates a new array, so you get a fresh copy every time. This means modifying the returned array does not affect the enum itself. For instance:

public enum Color { RED, GREEN, BLUE } Color[] colors = Color.values(); System.out.println(colors.length); // 3 System.out.println(colors[0]); // RED

The array is mutable, so you can change its elements, but those changes are local to that array instance. The enum constants themselves remain unchanged. This behavior is consistent across all Java versions.

Iterating Over Enum Constants

The most common use of values() is to iterate over all constants. A for-each loop is the clearest approach:

for (Color color : Color.values()) { System.out.println(color); }

You can also use streams to process constants functionally. Since values() returns an array, you can convert it to a stream with Arrays.stream:

Arrays.stream(Color.values()) .filter(c -> c.name().startsWith("R")) .forEach(System.out::println);

If you need the index while iterating, use a traditional indexed loop:

Color[] colors = Color.values(); for (int i = 0; i < colors.length; i++) { System.out.println(i + ": " + colors[i]); }

Remember that values() returns a new array each time, so if you call it inside a loop, you allocate a new array on every iteration. For small enums this is usually negligible, but for hot paths you might want to cache the result.

Using values() with Lookup and Switch

values() is often used to look up a constant by its ordinal or to build a mapping. For example, you can find a constant by its position:

Color color = Color.values()[1]; // GREEN

However, relying on ordinal is fragile if you reorder constants. The valueOf method is safer for name-based lookup:

Color color = Color.valueOf("BLUE");

values() also works well with switch statements when you need to handle all cases dynamically. You can iterate over the array and switch on each constant, though a direct switch on the enum type is more idiomatic.

Performance and Memory Considerations

The key performance characteristic of values() is that it creates a new array on every invocation. This involves allocating an array and copying references to the constants. For most applications, the cost is trivial, but if you call values() repeatedly in a tight loop or in a frequently invoked method, the allocation overhead can become measurable.

Consider this pattern:

for (int i = 0; i < 1_000_000; i++) { Color[] colors = Color.values(); // use colors }

Each iteration allocates a new array. Caching the array in a static final field avoids repeated allocation:

public class ColorCache { public static final Color[] VALUES = Color.values(); }

Then you can use ColorCache.VALUES instead of calling values() each time. This is safe because the array is read-only in practice; even if you modify it, the enum constants themselves are unaffected. The tradeoff is a static field that lives for the lifetime of the class, which is usually acceptable.

Alternatives to values() for Specific Use Cases

While values() gives you a raw array, Java provides specialized collections that can be more efficient for certain operations. EnumSet and EnumMap are designed for enums and offer better performance for membership tests and mapping operations.

For example, if you need to check whether a constant is in a set, EnumSet is more efficient than iterating over an array:

EnumSet<Color> warmColors = EnumSet.of(Color.RED, Color.ORANGE); if (warmColors.contains(color)) { // ... }

EnumMap provides a map with enum keys and uses an array internally, giving O(1) lookup. If your use case involves mapping each constant to a value, EnumMap is a better choice than building a Map manually from values().

For iteration, EnumSet also supports iteration in declaration order, so you can use it as a replacement when you need set semantics. However, values() remains the simplest way to get all constants as an array, and it is the foundation for many other operations.

Common Pitfalls and Edge Cases

One edge case is an empty enum. Although rare, you can declare an enum with no constants:

public enum EmptyEnum {}

EmptyEnum.values() returns an empty array, which is fine. Iterating over it simply does nothing.

Another pitfall is modifying the array returned by values(). Since it is a fresh copy, changes do not affect the enum, but they can cause confusion if you expect the array to be immutable. If you need an immutable list, wrap it with Collections.unmodifiableList(Arrays.asList(Color.values())).

Also, be careful when using ordinal() for persistence or external data. The ordinal is the position in declaration order, so reordering constants changes the ordinal values. If you store ordinals in a database, a reorder can break data integrity. Use the name() method or a custom field for stable identifiers.

When to Cache the values() Result

Caching the result of values() is a simple optimization that can reduce allocation pressure. The decision to cache depends on how often you call it and how large the enum is. For an enum with a handful of constants called occasionally, caching is unnecessary. For an enum with many constants used in a high-throughput path, caching avoids repeated array creation.

Here is a typical caching pattern:

public enum Status { NEW, PROCESSING, DONE; private static final Status[] VALUES = values(); public static Status[] all() { return VALUES; } }

Note that the static field is initialized when the enum class is loaded, so it is thread-safe. However, because the array is mutable, you should not expose it directly if you want to prevent external modification. Instead, return a copy or wrap it in an unmodifiable list.

Caching is a tradeoff between memory and CPU (avoiding allocation). In most applications, the allocation cost is negligible, so only cache when profiling indicates it matters. The important thing is to understand that values() returns a fresh array each time, and that behavior is by design—it protects the enum's internal state.

java enum values: How to Iterate Over All Constants | RYUSLOG DEV