Eugene
Eugene

Reputation: 60184

Using switch in Enum

What if I'll use switch in getByIntValue()? Is it really neccessary to use a SparseArray?

public enum Gender {
    Unknown(0),
    Male(1),
    Female(2);

    private static final SparseArray<Gender> lookupTable = new SparseArray<Gender>();
    static {
        for (final Gender gender : EnumSet.allOf(Gender.class)) {
            lookupTable.put(gender.intValue, gender);
        }
    }

    private final int intValue;

    public static Gender getByIntValue(int val) {
        return lookupTable.get(val);
    }

    private Gender(int intValue) {
        this.intValue = intValue;
    }

    public int getIntValue() {
        return intValue;
    }
}

Upvotes: 2

Views: 322

Answers (3)

Basil Bourque
Basil Bourque

Reputation: 338564

List.copyOf( EnumSet.allOf( Gender.class ) )

Caveat: This exercise in optimization seems silly for all but the most extreme scenario, as mentioned by JB Nizet. For real work, I would probably recommend the solution seen in the Answer by Marko Topolnik. But, for fun, I swung a bat at this ball.

Seems the goal is to render a static unmodifiable collection with very fast access by the given numbers 0, 1, 2.

As of Java 10, we have these new implemented (“default”) methods on the List interface: List.of & List.copyOf. These produce an unmodifiable collection. Though the backing implementation is undocumented and subject to change, I will assume it is something akin to an array with similar performance. Performance might even be faster than a conventional array, if the backing implementation detected the presence of an EnumSet and used some kind of bit vector.

I populate the List by passing an EnumSet to List.copyOf( Collection ).

So, this:

private static final SparseArray<Gender> lookupTable = new SparseArray<Gender>();
static {
    for (final Gender gender : EnumSet.allOf(Gender.class)) {
        lookupTable.put(gender.intValue, gender);
    }
}

…becomes this:

private static final List < Gender > lookupTable = List.copyOf( EnumSet.allOf( Gender.class ) );

Entire class, with main for demo.

package com.basilbourque.example;

import java.util.EnumSet;
import java.util.List;

public enum Gender {
    UNKNOWN( 0 ),
    MALE( 1 ),
    FEMALE( 2 );

    private static final List < Gender > lookupTable = List.copyOf( EnumSet.allOf( Gender.class ) );

    private final int intValue;

    public static Gender getByIntValue ( int val ) {
        return lookupTable.get( val );
    }

    public int getIntValue () {
        return intValue;
    }

    // Constructor
    private Gender ( int intValue ) {
        this.intValue = intValue;
    }

    public static void main ( String[] args ) {
        // Testing.
        System.out.println( Gender.UNKNOWN.intValue );
        System.out.println( Gender.getByIntValue( 0 ) );
        System.out.println( "----" );
        System.out.println( Gender.MALE.intValue );
        System.out.println( Gender.getByIntValue( 1 ) );
        System.out.println( "----" );
        System.out.println( Gender.FEMALE.intValue );
        System.out.println( Gender.getByIntValue( 2 ) );
    }

}

When run.

0

UNKNOWN


1

MALE


2

FEMALE


By the way, as the biological default, FEMALE should come before MALE.

Upvotes: 0

JB Nizet
JB Nizet

Reputation: 691715

Since your int values go from 0 to 2, without hole, you could indeed simply use an array. A switch would also be fine, although it would probably be slightly slower than an array lookup. But unless you call the method billions of times, it won't make any noticeable difference. Use what you find the clearest and easiest to understand and maintain.

Upvotes: 2

Marko Topolnik
Marko Topolnik

Reputation: 200158

If you have posted realistic int values, then you don't need to set them explicitly on each enum member, and don't need switch. Just use

Gender.values()[intValue]

Upvotes: 2

Related Questions