Cramer
Cramer

Reputation: 1795

Java: Using an enum as an array reference

I would like to reference an array with an enum type. This is a pretty standard thing in C++ (my origin), however I'm unsure if this is possible/desirable in Java.

For example, I would like to have an enum such as:

public enum Resource {
    COAL,
    IRON
}

Then later I would like to reference like this:

Amount[COAL] // The amount of coal
Price[IRON]  // The price of iron

I don't want to make Amount and Price fields of Resource as I would like a list of objects (orders for resources) grouped by the resource type. Manually assigning an int to each type of Resource is no better than public static int final BLAH I feel, nothing gained.

In essence, I'm looking for the enum of C++ which tags things. I realise that this could be the 'wrong' way of doing things in Java, so feel free to point me in the direction of the correct Java ethos.

Upvotes: 5

Views: 9188

Answers (6)

Gangnus
Gangnus

Reputation: 24464

Maps are very good for more dynamic data. But you also have to code all the checking for double names, double values, existing names/values and all the stuff. And even in this case if you do the error, it will be found at runtime only.

For more static data better use not primitive enums, but new type enums from Java 6. They are excellent! And errors will be found by compiler.

public enum Resource{
    COAL(0), IRON(1);
    int index;
    private Resource(int index){
        this.index=index;
    }
}
...
amount[Resource.COAL.index]=...

But better variant is:

public enum Resource{
    COAL(538,0.5f), IRON(115,1.5f);
    int amount;
    float price;
    private Resource(int amount, float price ){
        this.amount=amount;
        this.price=price;
    }
}
...
Resource.COAL.amount=...

You can use their name.

You could make the cycle through all enum:

for(Resource resourceType: Resource.values()) { 
   String toOutput=resourceType.name()+" amount="+ resourceType.amount;
}

Upvotes: 0

Andrzej Doyle
Andrzej Doyle

Reputation: 103777

In C++, an enum is effectively an alias for an integer. In Java, they're "proper" objects - which is why you can't use them as an array reference.

If you want to look up the value in your array that's associated with a particular enum object - that sounds like a Map to me! How about replacing those arrays with an EnumMap<Resource, Double>?

The EnumMap class is optimised for use with enum keys, such that it does end up using an array keyed on the enums' ordinal (integer) value behind the scenes. So it's much faster than a general-purpose hashmap, and you get the speed of an array-based solution with the semantic expressiveness of a Map - it's the best of both worlds.

Upvotes: 14

matthewSpleep
matthewSpleep

Reputation: 260

Each Java enum element has an ordinal associated with it, indexed from zero based on the order of definition in the enum. Just use e.g.

COAL.ordinal()

However, it sounds to me like you'd be better off creating a class e.g. Order with fields for Amount and Price and then keeping a collection of those e.g. in a Map indexed by the enum elements.

e.g.

Map<Resource, Order> orders = new HashMap<Resource, Order>();
orders.put(Resource.COAL, new Order(price, amount));

Upvotes: 1

hugeback
hugeback

Reputation: 1

I think you're looking for EnumMap, http://docs.oracle.com/javase/1.5.0/docs/api/java/util/EnumMap.html

It's not exactly an array, but because the key is an enum, it's still space efficient.

It ends up like:

amount.get(Resource.COAL)

Upvotes: 0

AlexR
AlexR

Reputation: 115328

You can do almost it. In contrast to C++ where enum is just an int, Java's enum is class. So you can't use it as an index of array. But every enum element has ordinal() that is int, so you can say

amount[COAL.ordinal()]
price[IRON.ordinal()]

But you have a better approach. Can add methods to enum, so it will look like:

IRON.price(amounts)
COAL.amount(prices)

I think this approach is much better.

Upvotes: 1

Jaco Van Niekerk
Jaco Van Niekerk

Reputation: 4182

Unfortunately, you'll need a slightly longer syntax:

Amount[COAL.ordinal()] // The amount of coal
Price[IRON.ordinal()]  // The price of iron

If that is not to your liking, constants may be your only option, i.e.

public class Resource {
    public static final int COAL = 0;
    public static final int IRON = 1;

}

Hope that helps.

Upvotes: -1

Related Questions