5

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.

6 Answers 6

14

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.

Sign up to request clarification or add additional context in comments.

1 Comment

Ahhh! This is exactly what I would like, thank you very much!
1

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.

Comments

1

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));

Comments

0

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)

Comments

0

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;
}

Comments

-1

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.

3 Comments

You really shouldn't use ordinal() - if one is to add another field in the enum, or even reorder it alphabetically, your code will break and it will be almost impossible to figure out why. A Map is a much more elegant and Java-like solution.
Perhaps not... but it answers the question Cramer had.
It (kind of) does, but it is also "the 'wrong' way of doing things in Java".

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.