Mapping specific strings to constant integers?
Given a specific set of strings, what's the best way to map them to a corresponding set of integers? Say I have a class with a few integer constants that I use internally, but need to take incoming external strings and determine the correct corresponding integer constant they map to.
Here's a simplified example:
public class Example {
public static final int ITEM_APPLE = 0;
public static final int ITEM_BANANA = 1;
public static final int ITEM_GRAPE = 3;
public void incomingDa开发者_如何学编程ta(String value) {
// Possible values would be "apple", "banana", and "grape" in this case.
}
}
What would the most appropriate approach be to go from that value to its corresponding integer constant? A HashMap? Or is ther any way to define these mappings in a static member? Another idea?
I would use a HashMap
as that is closest to what you want to achieve, and therefore a maintainable solution. You can define a static HashMap:
Class Example {
public static final int ITEM_APPLE = 0;
public static final int ITEM_BANANA = 1;
public static final int ITEM_GRAPE = 3;
private static final Map<String, Integer> fruitCodes = new HashMap<String, Integer>();
static {
fruitCodes.put("apple", ITEM_APPLE);
fruitCodes.put("banana", ITEM_BANANA);
// ...
}
public void incomingData(String value) {
// Possible values would be "apple", "banana", and "grape" in this case.
Integer code = fruitCodes(value);
if (null == code) {
throw new IllegalArgumentException("Forbidden fruit: " + value);
}
}
}
Yes, use an enum
. You can assign each enum an integer value, or just use ordinal()
public enum ExampleEnum {
ITEM_APPLE(0), ITEM_BANANA(1), ITEM_GRAPE(3);
private final int intValue;
private ExampleEnum (int intValue) {
this.intValue = intValue;
}
public int intValue() {
return intValue;
}
}
then use e.g. ExampleEnum.valueOf("ITEM_APPLE").intValue()
to resolve String to int
.
If the int values are sequential and zero-based, you can get rid of the intValue
field altogether:
public enum ExampleEnum {
ITEM_APPLE, ITEM_BANANA, ITEM_GRAPE;
}
and just use ExampleEnum.valueOf("ITEM_APPLE").ordinal()
you 'could' use reflection eg:
Example.class.getField("ITEM_" + input.toUpperCase()).getInt(null);
however, you should consider using Enums or if there aren't too many possibilities just use a set of else if
statements...
I also suggest an Enum method, although ExampleEnum.valueOf("ITEM_APPLE").ordinal() will have to do string comparisons to get to the answer while a HashMap will give you an O(1) complexity.
Probably a dangerous idea but just for fun (how about this):
class Example {
public static final int ITEM_APPLE = "apple".hashCode();
public static final int ITEM_BANANA = "banana".hashCode();
public static final int ITEM_GRAPE = "grape".hashCode();
public int incomingData(String value) {
return value.hashCode();
}
public static void main(String[] args) {
Example x = new Example();
if (ITEM_APPLE == x.incomingData("apple"))
System.out.println("ITEM_APPLE");
}
}
}
You just have to ensure the string value's hash codes does not clash ;-)
精彩评论