Get index of enum from string? - java

I have a string value, I also have an array of strings and an enum containing the range also.
To get the index of the string in the array, from the value supplied I write this:
Arrays.asList(myClass.BAUD_RATES).indexOf(username)
How do I do this for an enum? Can I use ordinal? Or do i have to make my own method?
The method might go like:
public enum Fruit {
...
static public boolean isMember(String aName) {
Fruit[] aFruits = Fruit.values();
for (Fruit aFruit : aFruits)
if (aFruit.fruitname.equals(aName))
return aFruit;
return false;
}
...
}

Not sure if I understand you correctly but based on question title you may be looking for
YourEnum.valueOf("VALUE").ordinal();
//like Directions.valueOf("NORTH").ordinal();
YourEnum.valueOf("VALUE") returns enum value with name "VALUE"
each enum value knows its position (indexed from zero) which we can get by calling ordinal() method on it.

I might not understand you question, but the same code works for enums too:
int index = Arrays.asList(YourEnum.values()).indexOf(YourEnum.ENUM_ITEM);
Or you can get:
int index = YourEnum.valueOf("ENUM_ITEM").ordinal();

Try this simple solution:
Fruit.values()[index]

If you want to retrieve the index, you can use ordinal. If you want to assign some specific value to String, you may define your own method to retrieve it.
enum DAY
{
MONDAY(10),
TUESDAY(20);
int value;
DAY(int x)
{
this.value = x;
}
public int getValue()
{
return value;
}
Now value and ordinal can be retrieved as :
for(DAY s : DAY.values() )
{
System.out.println(s.ordinal());
System.out.println(s.getValue());
}

The following logic will also work.
If you want to check and you know the fruitname already don't use for loop go with the approach mentioned by Pshemo
for (Fruit aFruit : aFruits)
if (aFruit.name().equals(aName))
return aFruit.ordinal();

Adding here the solution that worked for me:
YourEnum.values.indexOf("VALUE");

Related

Using integer values and String identifier in an Enum

So I currently have two enums:
public enum AuthorizationLevel
{
FULL,
HALF,
NONE;
};
public enum DatabaseLoggingLevel
{
HIGH,
MED,
LOW,
AUTH_ONLY,
NONE
}
I want to be able to associate integers with the values in the enums so that I can have code like so:
if(databaseLoggingLevel < ClassName.DatabaseLoggingLevel.HIGH) return;
This is just so that certain logging is disabled when the level is less than HIGH. I thought about making a helper function that returns an integer value associated with each enum value with a switch statement, but that seems hacky. Is there something I am missing?
You can add an integer instance field to your enum, and add a parameterized constructor:
enum AuthorizationLevel {
FULL(1), HALF(2), NONE(3);
private final int level;
private AuthorizationLevel(int level) {
this.level = level;
}
public int getLevel() {
return level;
}
};
Note that there is an ordinal() method which will give you position of your enum constants, but you should avoid using it. Again, quoting Effective Java Item - 31 (Use instance fields instead of ordinal):
If the constants are reordered, the numberOfMusicians method will
break. If you want to add a second enum constant associated with an
int value that you’ve already used, you’re out of luck.
Also, you can’t add a constant for an int value without adding
constants for all intervening int values. For example, suppose you
want to add a constant representing a triple quartet, which consists
of twelve musicians. There is no standard term for an ensemble
consisting of eleven musicians, so you are forced to add a dummy
constant for the unused int value (11). At best, this is ugly. If many
int values are unused, it’s impractical.
Modify the constructor of your enum to add the Integer value.
public enum DatabaseLoggingLevel {
HIGH(1),
MED(2),
LOW(3),
AUTH_ONLY(4),
NONE(5);
private final Integer value;
//For getByValue(). See Rohit's comment
private static final DatabaseLoggingLevel[] VALUES = DatabaseLoggingLevel.values();
private DatabaseLoggingLevel(Integer value) {
this.value = value;
}
public Integer getValue() {
return this.value;
}
//Bonus : getter by value:
public static DatabaseLoggingLevel getByValue(Integer value) {
for(DatabaseLoggingLevel e: VALUES) {
if(e.getValue().equals(value)) {
return e;
}
}
return null;
}
}
public enum DatabaseLoggingLevel
{
HIGH(1),
MED(2),
LOW(3),
AUTH_ONLY(4),
NONE(5)
private int code;
private DatabaseLoggingLevel(int code) {
this.code = code;
}
public int getCode() { return code; }
}
Use the ordinal() method. It gives you the position of the Value in the enum.
Rather than programming this in terms of "enums are numbers", program this in terms of "enums are smart". You can associate numbers with enums (after all, enums are instances of regular Java classes), but make that number private. Then you can add this method to the enum:
public boolean isAboveOrEqualTo(DatabaseLoggingLevel level) {
...
}
Then your conditional would look like this:
if (databaseLoggingLevel.isAboveOrEqualTo(ClassName.DatabaseLoggingLevel.HIGH)) {
...
}
Here is an explanation of how to associate numbers with enums: link.
While both of the answers given already will do what you want I would recommend looking at Log4J as an alternative to rolling your own logging levels
http://www.tutorialspoint.com/log4j/log4j_overview.htm

value of what the enum is currently set to

This should be total obvious, but it isn't. Is there a way to get the value of a enum as in the example below?
example:
public enum Numbers
{
zero, one, two
}
//later on
Numbers numbers = Numbers.zero;
// this is the part that I can not figure out the java equivalent of?
int number = numbers.value();
Does this make sense what I am trying to do?
It is generally considered bad practice to rely on ordinal since it is based on the order of the enum constants. A better solution would be to pass information to each instance. Just write a constructor and method like this:
public enum Number {
ZERO(0), ONE(1), TWO(2);
private int value;
private Number(int value) {
this.value = value;
}
public int value() {
return value;
}
};
Then you use it like you want
Number numbers = Number.ZERO;
int number = numbers.value();
and you won't have to worry about the actual order of the code if you add Numbers later.
Note: It is idiomatic in Java for enum names to be singular and for constants to be uppercase.
Based on your comments it appears you need to map an integer value to your enum to integrate it into another part of your code.
Rather than relying on the ordering you really want to do this yourself:
public enum MyEnum {
ZERO(0), ONE(1), TWO(2);
private int mapping;
MyEnum(int mapping) {
this.mapping = mapping;
}
public int getMapping() {
return mapping;
}
}
You could then compare via:
MyEnum e = MyEnum.ZERO;
if (someInt == e.getMapping()) { ... }
(Or even just MyEnum.ZERO.getMapping() )
You can use the ordinal() method. However, this is discouraged / risky, since if you ever change the order or arrangements of your enums, it will fail. e.g., you change to powers of two
public enum Numbers {
zero, one, two, four
}
then four.ordinal() will be 3.
If you really want a number associated with the enum, you should define your own method, e.g. order() or whatever. In the initial implementation it could return ordinal(), but, when you add four in the future, you can update that method.
p.s. Standard style is to capitalize the enums, e.g. ZERO, ONE, etc...
It depends on what you need. Here are 2 use cases:
1) You will probably need to test the value of an incoming "Numbers". For this use case, a switch case is the best solution.
void myMethod(Numbers n){
switch(n){
case zero:
//do something
break;
case one:
//do something
break;
//etc.
}
}
2) You can calso need to assign a value to each Numbers and be able to retrieve it. For this use case, you can define a constructor for your enum
public enum Numbers
{
zero(0), one(1), two(2);
private int value;
private Numbers(int value){
this.value=value;
}
}
Then, in your code, you can get this value:
void myMethod(Numbers n){
int value = n.getValue();
//do something with this value...
}
Last remark : Your enum names don't follow the java convention. They should be named with uppercase letters and eventually character '_'. ex: ONE, TWO, THREE, ANOTHER_VALUE

how to get a enum from a integer in java? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
How to get Enum Value from index in Java?
i have a enum like:
public enum EnumTest {
ONE, TWO, THREE
}
how i have a integer like 1=ONE 2=TWO 3=THREE
now i get a integer like 2 and want to generate the EnumTest from it and it should return TWO
how to do this?
Or, for more flexibility:
public enum EnumTest {
ONE(1), TWO(2), THREE(3);
private int value;
EnumTest(int value) {
this.value = value;
}
static EnumTest getByValue(int i) {
for (EnumTest e : values()) {
if (e.value == i) {
return e;
}
}
return null;
}
}
Think about future developpers which see this enum, if you leave an undocumented values() use, anybody can break it by adding new items. Because no documentation enforce the order of the elements.
You need to associate the int with a enum value.
You can do
static final EnumTest[] VALUE = { null, ONE, TWO, THREE };
return VALUE[num];
or
return EnumTest.values()[num-1];
or use a Map.
Get it like this EnumTest.values()[Number-1], where Number is your number (i.e. 1, 2, 3).
(Subtract 1 from the number because, for example, ONE will be at index 0, and EnumTest.values()[1] will give you TWO.)
If you just want the ordinal, here is some useful information:
you can get the ordinal of an enum constant with e.g. EnumTest.ONE.ordinal()
you can retrieve all enum constants with EnumTest.values()
From that, you can do what you want.
If you want to add a property with some arbitrary value, you can create a property + constructor + getter in your enum:
public enum EnumTest {
THREE(3), ONE(1), TWO(2);
private int val;
EnumTest(int val) { this.val = val; }
int getVal() { return val; }
}
This is more stable (values stay if you rename / insert / move them).
But are you sure you really need to get an int value? You should always work with the enum constants when possible e.g. EnumTest.THREE instead of 3.
I'd suggest to google for the various tutorials on java enums.
Try EnumTest.ordinal() for getting int values.
It will start from 0.
For getting enum from value, you can use EnumTest.values()[i].
Thanks.

Can I assume that Java enumerations auto-increment by 1?

Java states that the ordinal of the initial value is 0. Can I assume that when I create an enumeration like this :
public enum Direction {MONDAY, TUESDAY, WEDNESDAY, THURSDAY, ...}
That the ordinal of TUESDAY is always 1, that of WEDNESDAY always 2, ...?
I'll be a bit more specific. I'm declaring an enumeration :
public enum Direction {UP,RIGHT,DOWN,LEFT}
Now there's a method to turn 90 degrees (clockwise). It's one line with ordinals :
direction = Direction.values()[direction.ordinal()+1 % Direction.values().length];
If I wouldn't use ordinals I would have to use switch statements or conditions :
switch (direction) {
case LEFT:newdirection = Direction.UP;
break;
etc...
}
There are a couple advantages to using ordinals :
shorter code
faster code (negligeable)
if a direction is added (for example DOWN_LEFT) the implementation doesn't necessarily have to change if you put the new direction at the right spot
What do you think?
Yes - see javadoc:
Returns the ordinal of this enumeration constant (its position in its enum declaration, where the initial constant is assigned an ordinal of zero).
Yes - but your code should not rely on it because then it will break when someone inserts Caturday.
Yes, however, relying on this makes your code brittle. If you ever change the order of the constants in the enum or add constants between them, the ordinals of some of the constants will change. So, it is for example not a good idea to store ordinal numbers in a database or a file, because if your source code changes, the data in the database or file will not be compatible anymore with your changed code.
A more robust solution is to explicitly store codes with each of your constants. For example:
public enum Status {
NEW(0),
PROCESSING(1),
OK(2),
ERROR(99);
private final int code;
private Status(int code) {
this.code = code;
}
// Get the code for an enum constant
public int getCode() {
return code;
}
// Given a code, get the corresponding enum constant
public static Status fromCode(int code) {
for (Status s : Status.values()) {
if (s.code == code) {
return s;
}
}
throw new IllegalArgumentException("Invalid code: " + code);
}
}
You can also enforce indexes like this:
enum Direction {
MONDAY(1),
TUESDAY(2);
// etc...
private int value;
private Direction(int value) {
this.value = value;
}
public int getValue() {
return value;
}
}
Yes. However, relying on that is not the best idea if you ever want to reorder or add new enums in different places, or if you find a reason to change an existing value. I find it better to give them an actual value/meaning aside from their ordinal value and name.
The problem with ordinals is that they depend on the order of declaration of the enum values. If at some point a new value is added to the enumeration, and it's added in the middle of the others, then the ordinals will change, invalidating all code that depended on a specific ordinal value.
If you absolutely must assign a fixed number to an ordinal value, this might be of use:
enum Directions {
NORTH(1),
SOUTH(2),
WEST(3),
EAST(4);
private int code;
Directions(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
In the above snippet, a code attribute is associated to each enumeration value, and you can be sure that it will always have the same value - the one passed in the constructor.

Android Java cast long to enum problem

I have an issue with Java cast long type to Enum's type.
I'm using this code :
public enum RPCPacketDataType {
PT_JSON(1),
PT_BINARY(2);
private int value;
RPCPacketDataType(int i){
this.value=i;
}
public int getNumericType(){
return value;
}
}
static RPCPacketDataType tmpPacket_packetType;
And I need to do something like this :
case 2:
{
long intVal = Long.parseLong(thisPart);
if(intVal == 0){
isBad = true; break;
}
tmpPacket_packetType=intVal;
break;
}
where thisPart is just a string : String thisPart;
And the error says : Type mismatch: cannot convert from long to RPCCommucatorDefines.RPCPacketDataType
Any suggestions how to fix that?
You need to write a method, probably in RPCPacketDataType:
public static RPCPacketDataType valueOf(int value) {
...
}
Then call that from your case statement. Given that the value can only be an integer, you should almost certainly be using Integer.parseInt instead of Long.parseLong.
How you implement the valueOf method is up to you - you could iterate through the EnumSet of all values trying to find a match, or create a HashMap from Integer to RPCPacketDataType, or potentially just an array (with validation). It will depend on what's in your enum, and how many values there are to look through.
Note that you should also consider what to do if valueOf is passed a value which doesn't correspond to any enum value - one option is to return null (and probably test for that explicitly in the calling code); another is to throw an exception.

Categories