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

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.

Related

When should I use the final keyword instead of enums?

I had the following field in my code:
private static final int NUM_NANOSECONDS_IN_MILLISECOND = 1000000;
I was told that I should be using an enum for this for type safety. This is not something I am familiar with. But if this is the case, I don't know when it would ever be appropriate to use the final keyword on a field.
When should I use the final keyword instead of enums?
Constants are just that, constants with a name.
Enums are literal constants that have a value. I explain...
Consider:
public final static int NORTH = 0;
public final static int SOUTH = 1;
public final static int EAST = 2;
public final static int WEST = 3;
and
public enum Direction {
NORTH, SOUTH, EAST, WEST
}
From a readability standpoint it kinda looks the same:
if(direction == NORTH)
or with enums:
if(direction == Direction.NORTH)
Where things might go wrong is that with the final constant, you can also do
if(direction == 0)
Now it's more difficult to understand the code even though it does the same thing. With enums, you just can't do that so it's let problems.
Similarly, when expecting a direction as a method argument:
with final static:
public void myMethod(int direction)
and with enums:
public void myMethod(Direction direction)
It's clearer, and less opportunities for problems.
This is just a beginning. Enums can actually have methods that help you better manage the information they contain. Read up here for a clean explanation.
Example:
public enum Direction {
NORTH (0, 1),
SOUTH (0, -1),
EAST (1, 0),
WEST (-1, 0)
private int xDirection, yDirection;
Direction(int x, int y) {
this.xDirection = x;
this.yDirection = y;
}
public Vector2D getTranslation() {
return new Vector2D(this.xDirection, this.yDirection);
}
}
So then in your code:
public void moveThePlayer(Player p, Direction d) {
p.translate(d.getTranslation());
}
moveThePlayer(p, Direction.NORTH);
This becomes really hard to do with final static. Or at least, it gets very unreadable.
All this being said, with the particular case you are working with there, if there's only one numeric constant value, I'd keep the final static. No point using an enum if there's a single value.
Using an enum avoids using an int, not final. Using a dedicated enum provides type safety, so you can have clearer method signatures and avoid bugs. final is used to prevent changing a value once set, and is a generally good practice regardless of the variable's type.
In this case however I'm not sure what value an enum gives you. NUM_NANOSECONDS_IN_MILLISECOND doesn't seem like it should be a dedicated type, and as #BoristheSpider suggests, you shouldn't need this field at all. Perhaps your associate was suggesting using an enum for the unit (e.g. NANOSECOND, MILLISECOND, etc) rather than storing ratios like this. In that case, the existing TimeUnit enum is definitely your friend.
It honestly depends on what you need. enum as its name shows stands for enumeration.
Enumerations have multiple elements like so
public enum Colors {
CYAN, MAGENTA, YELLOW, BLACK
}
You could even give them numerical values or so! Because enums are cool.
public enum RGBColors {
RED(0xFF0000), GREEN(0x00FF00), BLUE(0x0000FF);
private int hexacolor;
private RGBColors(int hexacolor) {
this.hexacolor = hexacolor;
}
public int getColorValue() {
return hexacolor;
}
}
Your case is just a numerical constant. A single numerical constant.
public static final long SUCH_NUMERICAL_VALUE = 12367160L;
This is just a constant. This is not an enumeration. There is also no reason for it to be an enumeration, as you are just using it as a number.
The biggest advantage (in my opinion) of an enum is that you can iterate on every element of its type.
for(RGBColors rgbColor : RGBColors.values()) {
... //do things with rgbColor for each of them
}
You cannot do that with public static final int. I even wrote an enum wrapper around a bunch of public static final properties here because of this problem: https://stackoverflow.com/a/28295134/2413303
More importantly, you can easily read what value stands for what without having to go deep into the source:
RGBColors red = RGBColors.RED;
Now let's see this with int:
int red = RGBColors.RED;
I could just say
int red = 0; //red color
Who will tell what on earth that is later? Who knows!
Anyways, the short answer is, enums are great when you're specifying enumerations, aka multiple elements (or you're creating enum singletons), and these elements need to have extra methods or properties.
public enum MySingleton { //this is an enum singleton
INSTANCE;
public void doThings() {
System.out.println("hello!");
}
}
MySingleton.INSTANCE.doThings(); //hello!
Constants (public static final) are great when you use them as exactly that: constants.
I would say that the general use case for enums would be when you have a small finite set of values that form some set you are modeling and you are going to enumerate each one. They can also help ensure that a field that should contain one of these values does not contain some other value.
In this case, neither seems to apply. You could just as well have NUM_NANOSECONDS_IN_MICROSECOND, NUM_NANOSECONDS_IN_SECOND, NUM_NANOSECONDS_IN_PI_MILLISECONDS, and so on, and you aren't going to enumerate each one. Furthermore, it would seem that the variables you are going to be storing these values in probably shouldn't be restricted to the values of the defined constants.
When writing source code it is best to rely on the compiler as much as possible to help you find logic errors. One way is to use variable and constant types so that if you use the wrong constant for a method, the compiler will flag this as an error.
The advice is not really about using final versus enum since those are really two different programming concepts. It is instead using an enum to create an explicit and unique type versus using an int which is much less explicit and unique. If you use int as part of the method signature for a function that is supposed to take nanoseconds then any int value will be accepted by the compiler. If you instead use an enum then only those values that are specified in the enum are allowed. Using anything else will cause the compiler to issue an error.
The final keyword is a way of making sure that the variable can not be overriden or modified so that the variable acts like a constant. wikipedia article on final.
The values specified in an enum are constants so you can choose between using what you have, a constant, or using an enum, a constant, however using the enum will provide a safety check from the compiler so that only the specified values of the enum can be used in a method call or variable assignment for nanoseconds.
Here is an explanation of final with additional links from that stack overflow. Java method keyword final and its use also provides some additional information.
See What is the purpose of Enum for some explanation about enum.

Require input regarding JAVA ENUMS

Consider the following
public enum tc implements {
NORESULTS(0), GOOD_RESULTS(1), EXCELLENT_RESULTS(2), NO_DATA_AVAILABLE(5), SOME_OTHER_VALUE(4);
private final Integer value;
// Code for the constructor, getters and setters for the value****
The enum tc values correspond to the testValue in the below class.
public class TestData {
private int testID;
private String testName;
private int testValue;
....
...
}
In the Results class, the TestDataList has to be sorted by a different order of ranking rather than testValue.For example Excellent followed by Good Results followed by NoResults etc..
public class Results {
List<TestData> TestDataList = getTestData();
I can code for the comparator etc..the question is since I require a different ordering for the enums which of the following two options is better
a) add private int rankTestValue in the enum tc. This option may require that I have to write a method getRank(int value) that would return the corresponding rankTestValue based on the value.
OR
b) add in Results class a map Map tcRankMap = new HashMap();. Populate this map with key values like (2,1) (1,2) corresponding to (enum values, ranking).For example (2,1) would be Excellent_Results has first ranking etc.
Which of these two options would be better. If there are better solutions then please let me know.
Option (a) looks better and according to Object Oriented Analysis and Design.
The good news is that the is a question of implementation detail which can be encapsulated into your Comparator anyway, so it doesn't matter so much.
As for style and readability, I would prefer (a), but it's down to personal preference.
There is also a solution (c) - use the ordinal(), and then sort them according to rank. Just add a comment to make it clear
public enum tc implements {
// NB: enum values are sorted according to rank
EXCELLENT_RESULTS(2),
GOOD_RESULTS(1),
NORESULTS(0),
NO_DATA_AVAILABLE(5),
SOME_OTHER_VALUE(4);
private final Integer value;
// Code for the constructor, getters and setters for the value****
}
Your first option would look like this:
enum TestScore {
EXCELLENT(5),
NO_RESULT(2),
POOR(1);
private final int order;
private TestScore(int order) {
this.order = order;
}
public int compareOrderTo(TestScore other) {
return this.order - other.order;
}
}
You could then add a comparison method to TestData
public int compareTestScore(TestData other) {
return this.testScore.compareOrderTo(other.testScore);
}
And sort your list with:
Collections.sort(testData, TestData::compareTestScore);
The problem with this is that the order field is really completely arbitrary and needs to be updated each time you add a new entry. However that's definitely better and more explicit than using the natural ordering of the enum (i.e. it's ordinal value which should be entirely incidental to avoid fragility).

Convert from String to a Java enum with large amount of values [duplicate]

This question already has answers here:
How to get an enum value from a string value in Java
(32 answers)
Closed 7 years ago.
Let's say I have an enum with 100 values. For simplicity's sake, take the following example:
public enum code
{
CODE_1("string1"),
CODE_2("string2"),
CODE_3("string3"),
CODE_4("string4"),
...
}
I want to create a public method to convert strings with a known format (like "string1", "string2"...) to the appropiate enum value CODE_1, CODE_2... Typically this is done by iterating over all values, and if a match is found, return that enum value. (Details can be found in this question.)
However, I'm concerned with reguraly looping over all values. Could this potentially be a huge bottleneck? What if instead of 100 element, there were 1000?
As an exercise for myself, I tried to optimize this lookup with a static map, which can assure O(1) lookup time given any string. I like this extra gimmick, but I only want to include it in my code if it is actually necessary. What are your thoughts and findings on using the iterating method vs the map method?
public enum Code
{
...
//enum values
...
//The string-to-Code map
private static final Map<String,Code> CODE_MAP = populateMap();
private static Map<String,Code> populateMap()
{
Map<String,Code> map = new HashMap<String,Code>();
for(Code c : Code.values())
{
map.put(c.getCode(), c);
}
return map;
}
private String code;
private Code(String code)
{
this.code = code;
}
public String getCode()
{
return this.code;
}
public Code convertFromString(String code)
{
//assume that the given string is actually a key value in the map
return (Code) CODE_MAP.get(code);
}
}
You want a Map<String, Code>, but how to populate it neatly? Enums don't allow you to initialize a static fields before the enum instances are initialized, but there's a neat little trick, called the Initialization-on-demand holder idiom, that makes using a statically initialized map needed for this functionality easy to implement:
public enum Code {
CODE_1("string1"),
CODE_2("string2"),
CODE_3("string3"),
// etc
;
private static class Holder {
static Map<String, Code> CODE_MAP = new HashMap<>();
}
private final String code;
private Code(String code) {
this.code = code;
Holder.CODE_MAP.put(code, this);
}
public String getCode() {
return this.code;
}
public Code convertFromString(String code) {
return Holder.CODE_MAP.get(code);
}
}
This works because the class loader initializes inner static classes before initializing the enum class, so the map is assigned ready to load during enum instance initialization.
No loops. No special code to load the map (done in constructor). Minimal code.
Map is good option : cleaner code and O(1) . If you use for-loop then the best you get is O(n)
Your provided solution is proper implementation.
As you will have to expose only one method and it is more readable.
And it is always good to use Map instead of iterating it manually.
And also as you mentioned the complexity is O(1).
+1 to your question, as it gives a cleaner approach to use enum in some usecases.
If your string code value is a known and consistent format you could avoid the use of a Map and the memory it consumes and construct the CODE enum lookup value on the fly:
public static Code convertFromString(String code) {
return valueOf("CODE_" + code.substring("string".length()));
}
Well, alternatives to the map-solution would be a giant switch-statement (could be automatically generated) or binary-searching an array containing the strings. I don't think either will beat HashMap's performance by a large margin, though if it really matters, you are probably best off by benchmarking.
One thing that has not been mentioned is how Enum.valueOf() let's you turn a String into an enum value, if it has the exact name of one of the enum members. If this is at all a possiblity in your case (looking just at your example, I don't see how Code.CODE_1 could not be easily renamed Code.string1 etc.), I would suggest using it, as it requires no additional coding at all and will hence be the most understandable.

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

Categories