Associate enum value to integer - java

I have this enum:
public enum Digits {
ZERO(0);
private final int number;
private Digits(int number) {
this.number = number;
}
public int getValue(){
return number;
}
}
And I would like to make setter in another class which can me offer following feature:
- I will give it integer value (in this case, 0) and that setter will set enum ZERO to my local variable of type Digits
Is that possible?
Many thanks!

It is possible, but not by invoking the enum's constructor, as it's available only within the enum itself.
What you can do is add a static method in your enum that retrieves the correct instance based on a given value, e.g. ZERO if the given value is 0.
Then you'd invoke that method in your other class when given the int argument.
Self contained example
public class Main {
static enum Numbers {
// various instances associated with integers or not
ZERO(0),ONE(1),FORTY_TWO(42), DEFAULT;
// int value
private int value;
// empty constructor for default value
Numbers() {}
// constructor with value
Numbers(int value) {
this.value = value;
}
// getter for value
public int getValue() {
return value;
}
// utility method to retrieve instance by int value
public static Numbers forValue(int value) {
// iterating values
for (Numbers n: values()) {
// matches argument
if (n.getValue() == value) return n;
}
// no match, returning DEFAULT
return DEFAULT;
}
}
public static void main(String[] args) throws Exception {
System.out.println(Numbers.forValue(42));
System.out.println(Numbers.forValue(10));
}
}
Output
FORTY_TWO
DEFAULT

You can do it like this:
private Digits digit;
public void setDigit(int number) {
for (Digits value : Digits.values()) {
if(value.getValue() == number) {
digit = value;
}
}
}

Here is the example how to achieve what you want
public enum Digit {
ONE(1),
TWO(2),
THREE(3);
private static final Map<Integer, Digit> mappingMap = new HashMap<Integer, Digit>();
static {
for (Digit m : Digit.values()) {
mappingMap.put(m.getValue(), m);
}
}
private final int digit;
Digit(int aDigit) {
digit = aDigit;
}
public int getValue() {
return digit;
}
public static Digit getByDigit(int aDigit) {
return mappingMap.get(aDigit);
}
}
This approach has better performance than iterating over all constants for large enums.

Related

How to print the value of Enum which is passed as parameter in the function in Java?

My requirement is I want to pass the Enum as the parameter in the function,and from the function want to print the value of Enum. For Example Enum, Category.ONE should print 1. Similarly for TWO should print 2 and for THREE should print 3.
I assigned the value Enum, like 1, 2, 3.
enum Category {
ONE(1),
TWO (2),
THREE(3);
private final Integer num;
Category(Integer val) {
num = val;
}
}
public class EnumDemo1 {
public static void printEnumValue(Category category){
System.out.println(category.name()); // Want to print the value of ENUM. 1, 2, 3
}
public static void main(String[] args) throws Exception {
for(Category category: Category.values()){
printEnumValue(category);
}
}
}
You can add a method that returns num, e.g.:
enum Category {
ONE(1),
TWO (2),
THREE(3);
private final Integer num;
Category(Integer val) {
num = val;
}
public int getValue() {
return num;
}
}
And then, call it from printEnumValue, e.g.:
public static void printEnumValue(Category category){
System.out.println(category.getValue()); // Want to print the value of ENUM. 1, 2, 3
}
Declare a getter for the field, or make it public:
enum Category {
ONE(1),
TWO (2),
THREE(3);
private final Integer num;
Category(Integer val) {
num = val;
}
public int getNum() {
return num;
}
}
public class EnumDemo1 {
public static void printEnumValue(Category category){
System.out.println(category.getNum()); // Want to print the value of ENUM. 1, 2, 3
}
public static void main(String[] args) throws Exception {
for(Category category: Category.values()){
printEnumValue(category);
}
}
}
Also, enums have ordinals, which return an integer, describing the order of the enum value.
remove final modifier for num field and declare getter method
enum Category {
ONE(1),
TWO (2),
THREE(3);
//
private Integer num;
Category(Integer val) {
this.num = val;
}
public int getValue() {
return num;
}
}
public class EnumDemo1 {
public static void printEnumValue(Category category){
System.out.println(category.getValue()); // Want to print the value of ENUM. 1, 2, 3
}
public static void main(String[] args) throws Exception {
for(Category category: Category.values()){
printEnumValue(category);
}
}
}
see https://docs.oracle.com/javase/tutorial/java/javaOO/enum.html for more

How to isolate conversion of Strings to different Classes in Java?

I have an initial set of data that can come in two different formats that need to be matched against. The entries will be either an exact match or provide a range. The range values will be integers in decimal format - but the data to match could be hex as well as decimal. The base will be indicated within the initial data. So the initial data will look something like the following (JSON formatted):
[
{"value":"X"},
{"value":"Y"},
{"START":"0000", "END":"0010", "INPUTBASE":"10"},
{"START":"0200", "END":"0300", "INPUTBASE":"16"}
]
So I need a function something like boolean contains(final String value) that would check to see if value is contained in the "keeper" set The strings X, Y, 8, FF would all hit - FF as a hex number (multiple matches are not a concern). What I have done is create two sets one with single values and one with Ranges wrapped to include the base. My code is something like the following:
Set<WrappedRange> wrappedRangeSet;
Set<String> singleEntrySet;
public boolean contains(final String value) {
return singleEntrySet.contains(value) || valueInRange(value);
}
private boolean valueInRange(final String incoming) {
Long value;
for(WrappedRange<Long> wrappedRange : wrappedRangeSet) {
try {
value = Long.valueOf(incoming, wrappedRange.getBase());
} catch (NumberFormatException nfe) {
continue; // not worried if wrong format...
}
if (wrappedRange.contains(value)) {
return true;
}
}
return false;
}
The WrappedRange looks like:
class WrappedRange<C Extends Comparable> {
private final int base;
private final Range<C> range;
public WrappedRange(final Range<C> range, final int base) {
this.range = range;
this.base = base;
}
public boolean contains(final C value) {
return range.contains(value);
}
public int getBase() {
return int base;
}
}
At the minimum I would like to get rid of the WrappedRange.getBase() method and move the conversion from String to the desired type into the WrappedRange class. Then a contains(String) method could be added to WrappedRange class. The loop in the valueInRange method be reduced to:
for(WrappedRange<Long> wrappedRange : wrappedRangeSet) {
if (wrappedRange.contains(value)) {
return true;
}
}
The problem I'm running into is that I've made the assumption the value I am comparing is a Long, and not any extension of Comparable. I could just fix the WrappedRange to use Longs, but then I can't use the class for other Comparables.
Ideally I'd like to restrict the conversion of the Strings to the WrappedRange class, as there is the possibility other extensions of Comparable may be used for input to the contains function in the future. The class would look something like the following:
class WrappedRange<C Extends Comparable> {
private final int base;
private final Range<C> range;
public WrappedRange(final Range<C> range, final int base) {
this.range = range;
this.base = base;
}
public boolean contains(final C value) {
return range.contains(value);
}
public boolean contains(final String incoming) {
C value = convert(incoming);
return range.contains(value);
}
private convert(final String incoming) {
// ... convert to type C and return.
}
}
Is there a simple way to do this? Is it even possible?
If the input will always be a string, and the internal structure will always be a range, why not do something like this?
public abstract class WrappedRange<C extends Comparable> {
private final Range<C> range;
protected WrappedRange(Range<C> range) {
this.range = range;
}
public boolean contains(String incoming) {
try {
C value = convert(incoming);
} catch (Exception ex) {
return false;
}
return range.contains(value);
}
protected abstract C convert(String incoming);
}
class WrappedLongRange extends WrappedRange<Long> {
private final int base;
WrappedLongRange(Range<Long> range, int base) {
super(range);
this.base = base;
}
#Override
protected Long convert(String incoming) {
return Long.valueOf(incoming, base);
}
}

DRY maxima tracking

Suppose I am importing table entries, where a single entry can be stored in a class:
class Foo {
int i1;
int i2;
double d1;
}
After the import is complete, I will need to have access to the imported values themselves, as well as to their normalized versions. So far, I have implemented this functionality as follows:
class FooWithMaxTracking {
private int i1;
private static int i1_max=0;
public void setI1(int value){
this.i1 = value;
if (value > i1_max) { i1_max = value; }}
public int getI1(){
return i1;}
public double normI1(){
return i1/((double)i1_max);}
private int i2;
private static int i2_max=0;
public void setI2(int value){ <code identical to written above> }
public int getI2(){ ... }
public double normI2(){ ... }
// and another set of similar 2 variables & 3 functions for 'double d1'
}
In this implementation I strongly dislike the fact that I had to write the same code many times (only three in this example, but about ten times in the real project). Is there any way to make the code more DRY ("don't repeat yourself")?
If you do not mind a slight loss of performance, you can put all the maxima in a static Map, define a class that holds a getter, a setter, and a norm methods, and replace the individual variables with instances of that class:
private static Map<String,Object> max = new HashMap<String,Object>();
private static class IntMaxTrack {
private final String key;
private int value;
public IntMaxTrack(String k, int v) {
key = k;
value = v;
max.put(key, value);
}
public int get() { return value; }
public void set(int v) {
int m = ((Integer)max.get(key)).intValue();
value = v;
if (value > m) {
max.put(key, value);
}
}
public double norm() {
int m = ((Integer)max.get(key)).intValue();
return val / ((double)m);
}
}
Make a similar class for double, i.e. DblMaxTrack Now you can replace primitives with instances of these classes, and call their get, set, and norm from the corresponding methods of your class.
What about defining one class with the necessary code, like:
public class Bar {
private int i1;
private static int i1_max = 0;
public void setI1(int value) {
// ...
}
public int getI1() {
// ...
}
public double normI1() {
// ...
}
}
And using it sevearl times, like:
class FooWithMaxTracking {
one = new Bar();
two = new Bar();
three = new BarForDouble();
}

Implementing Static Methods In A Class

From a book I'm going through:
"Design a class name MyInteger. The class contains:
...blah, blah, blah...
The methods isEven(), isOdd(), and isPrime() that return true if the value in this object is even, odd, or prime, respectively.
The static methods isEven(int), isOdd(int), and isPrime(int) that return true if the specified value is even, odd, or prime, respectively.
The static methods isEven(MyInteger), isOdd(MyInteger), isPrime(MyInteger), that return true if the specified value is even, odd, or prime, respectively."
Here's what I've got so far. The top is easy to implement with object.isEven()...
The second, I assume this is just to display results without actually setting the value and changing the object? So I could just do object.isEven(2)?
The last one... that's throwing me off a lot. I have no idea. =/ Please help me out. Thanks in advance.
To clarify:
1.
public boolean isEven(){
// code
}
MyInteger object = new MyIntger(50);
object.isEven();
2.
public boolean isEven(int num){
// code
}
MyInteger.isEven(50)???
3.
public boolean isEven(int MyInteger)???
???
class MyInteger {
int number;
// CONSTRUCTOR
public MyInteger(int a) {
number = a;
}
public int getNumber() {
return number;
}
static boolean isEven(MyInteger myint) {
if (myint.getNumber() % 2 == 0)
return true;
else
return false;
}
}
Now the main class:
public class MainClass {
/**
* #param args
*/
public static void main(String[] args) {
// TODO Auto-generated method stub
MyInteger myInteger=new MyInteger(10);
boolean result=MyInteger.isEven(myInteger);
if(result==true)
System.out.println("true result");
else
System.out.println("false result");
}
}
This seems to be the one that's confusing
boolean odd2 = MyInteger.isOdd(new MyInteger(5)); // static call
You use use an instance of MyInteger to pass as an argument. Another way to pass MyInteger as an argument is:
MyInteger num = new MyInteger(5);
boolean odd2 = MyInteger.isOdd(num); // static call
class MyInteger{
int num;
public MyIntger(int num){
this.num = num;
}
// Method 1
public static boolean isOdd(int num){
...
}
// Method 2
public boolean isOdd(){
...
}
// Method 3
public static boolean isOdd(MyInteger num){
...
}
}
public class TestMyInteger{
public static void main(String[] args){
// Method 1 call
boolean odd1 = MyIntger.isOdd(5); // static call
// Method 3 call
boolean odd2 = MyInteger.isOdd(new MyInteger(5)); // static call
// Method 2 call
MyIntger num = new MyIntger(5); // create instance
boolean odd3 = num.isOdd(); // instance call
System.out.println(odd1);
System.out.println(odd2);
System.out.println(odd3);
}
}
For second one, the method is belong to the class. But not the created object.
If Your code like this :
MyInteger myInteger = new MyInteger(100);
You can call the method by this
MyInteger.isEven(50);
or
myInteger.isEven(50);
It is not related to 100 which set in object.
Consider this as a pointer, and then you might want to look at this question.
public class MyInteger {
private int value;
public MyInteger(int value) {
super();
this.value = value;
}
public static boolean isPrime(int value) {
// I would increment counter then test if the result of value modulo counter
// (that is if value % counter != 0) until counter >= square_root(value).
// Then the value is prime, otherwise
return false;
}
public static boolean isEven(int value) {
return (value & 1) == 0;
}
public static boolean isEven(MyInteger m) {
return isEven(m.value);
}
public static boolean isPrime(MyInteger m) {
return isPrime(m.value);
}
public static boolean isOdd(int value) {
return !isEven(value);
}
public static boolean isOdd(MyInteger m) {
return isOdd(m.value);
}
public boolean isEven() {
return isEven(this.value);
}
public boolean isOdd() {
return isOdd(this.value);
}
public boolean isPrime() {
return isPrime(value);
}
public int getValue() {
return value;
}
public void setValue(int value) {
this.value = value;
}
}
You would be performing actions upon the MyInteger object rather than just a straight int.
Let's say your private variables and constructor look like this (we don't know exactly because it isn't posted):
private int myInt;
public MyInteger(int thisInt) {
myInt = thisInt;
}
You will need to implement an accessor method that returns the value of myInt within an instance of the MyInteger class and then use this accessor method in your static method to perform the operation.
So as an accessor method:
public int getInt()
{
return myInt;
}
And then your static method would reference this method in the same way you would in another program. Note that you have to specify the use of the MyInteger object even within the class:
public static boolean isEven(MyInteger myInteger)
{
//Code here
}
In terms of calling the static method, it would look something like this:
MyInteger myInteger = new MyInteger(50);
MyInteger.isEven(myInteger);
Here, you are referencing an instance of the MyInteger object (myInteger) rather than the primitive int, but because isEven isn't directly connected to a specific object, you have to tell your code where to find the isEven() method, the MyInteger class.

Cast Int to enum in Java

What is the correct way to cast an Int to an enum in Java given the following enum?
public enum MyEnum
{
EnumValue1,
EnumValue2
}
MyEnum enumValue = (MyEnum) x; //Doesn't work???
Try MyEnum.values()[x] where x must be 0 or 1, i.e. a valid ordinal for that enum.
Note that in Java enums actually are classes (and enum values thus are objects) and thus you can't cast an int or even Integer to an enum.
MyEnum.values()[x] is an expensive operation. If the performance is a concern, you may want to do something like this:
public enum MyEnum {
EnumValue1,
EnumValue2;
public static MyEnum fromInteger(int x) {
switch(x) {
case 0:
return EnumValue1;
case 1:
return EnumValue2;
}
return null;
}
}
If you want to give your integer values, you can use a structure like below
public enum A
{
B(0),
C(10),
None(11);
int id;
private A(int i){id = i;}
public int GetID(){return id;}
public boolean IsEmpty(){return this.equals(A.None);}
public boolean Compare(int i){return id == i;}
public static A GetValue(int _id)
{
A[] As = A.values();
for(int i = 0; i < As.length; i++)
{
if(As[i].Compare(_id))
return As[i];
}
return A.None;
}
}
You can try like this.
Create Class with element id.
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public static MyEnum fromId(int id) {
for (MyEnum type : values()) {
if (type.getId() == id) {
return type;
}
}
return null;
}
}
Now Fetch this Enum using id as int.
MyEnum myEnum = MyEnum.fromId(5);
I cache the values and create a simple static access method:
public static enum EnumAttributeType {
ENUM_1,
ENUM_2;
private static EnumAttributeType[] values = null;
public static EnumAttributeType fromInt(int i) {
if(EnumAttributeType.values == null) {
EnumAttributeType.values = EnumAttributeType.values();
}
return EnumAttributeType.values[i];
}
}
Java enums don't have the same kind of enum-to-int mapping that they do in C++.
That said, all enums have a values method that returns an array of possible enum values, so
MyEnum enumValue = MyEnum.values()[x];
should work. It's a little nasty and it might be better to not try and convert from ints to Enums (or vice versa) if possible.
This not something that is usually done, so I would reconsider. But having said that, the fundamental operations are: int --> enum using EnumType.values()[intNum], and enum --> int using enumInst.ordinal().
However, since any implementation of values() has no choice but to give you a copy of the array (java arrays are never read-only), you would be better served using an EnumMap to cache the enum --> int mapping.
Use MyEnum enumValue = MyEnum.values()[x];
Here's the solution I plan to go with. Not only does this work with non-sequential integers, but it should work with any other data type you may want to use as the underlying id for your enum values.
public Enum MyEnum {
THIS(5),
THAT(16),
THE_OTHER(35);
private int id; // Could be other data type besides int
private MyEnum(int id) {
this.id = id;
}
public int getId() {
return this.id;
}
public static Map<Integer, MyEnum> buildMap() {
Map<Integer, MyEnum> map = new HashMap<Integer, MyEnum>();
MyEnum[] values = MyEnum.values();
for (MyEnum value : values) {
map.put(value.getId(), value);
}
return map;
}
}
I only need to convert id's to enums at specific times (when loading data from a file), so there's no reason for me to keep the Map in memory at all times. If you do need the map to be accessible at all times, you can always cache it as a static member of your Enum class.
In case it helps others, the option I prefer, which is not listed here, uses Guava's Maps functionality:
public enum MyEnum {
OPTION_1(-66),
OPTION_2(32);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static ImmutableMap<Integer, MyEnum> reverseLookup =
Maps.uniqueIndex(Arrays.asList(MyEnum.values())), MyEnum::getValue);
public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
}
With the default you can use null, you can throw IllegalArgumentException or your fromInt could return an Optional, whatever behavior you prefer.
Based on #ChadBefus 's answer and #shmosel comment, I'd recommend using this. (Efficient lookup, and works on pure java >= 8)
import java.util.stream.Collectors;
import java.util.function.Function;
import java.util.Map;
import java.util.Arrays;
public enum MyEnum {
OPTION_1(-66),
OPTION_2(32);
private int value;
private MyEnum(final int value) {
this.value = value;
}
public int getValue() {
return this.value;
}
private static Map<Integer, MyEnum> reverseLookup =
Arrays.stream(MyEnum.values()).collect(Collectors.toMap(MyEnum::getValue, Function.identity()));
public static MyEnum fromInt(final int id) {
return reverseLookup.getOrDefault(id, OPTION_1);
}
public static void main(String[] args) {
System.out.println(fromInt(-66).toString());
}
}
You can iterate over values() of enum and compare integer value of enum with given id like below:
public enum TestEnum {
None(0),
Value1(1),
Value2(2),
Value3(3),
Value4(4),
Value5(5);
private final int value;
private TestEnum(int value) {
this.value = value;
}
public int getValue() {
return value;
}
public static TestEnum getEnum(int value){
for (TestEnum e:TestEnum.values()) {
if(e.getValue() == value)
return e;
}
return TestEnum.None;//For values out of enum scope
}
}
And use just like this:
TestEnum x = TestEnum.getEnum(4);//Will return TestEnum.Value4
I hope this helps ;)
Wrote this implementation. It allows for missing values, negative values and keeps code consistent. The map is cached as well. Uses an interface and needs Java 8.
Enum
public enum Command implements OrdinalEnum{
PRINT_FOO(-7),
PRINT_BAR(6),
PRINT_BAZ(4);
private int val;
private Command(int val){
this.val = val;
}
public int getVal(){
return val;
}
private static Map<Integer, Command> map = OrdinalEnum.getValues(Command.class);
public static Command from(int i){
return map.get(i);
}
}
Interface
public interface OrdinalEnum{
public int getVal();
#SuppressWarnings("unchecked")
static <E extends Enum<E>> Map<Integer, E> getValues(Class<E> clzz){
Map<Integer, E> m = new HashMap<>();
for(Enum<E> e : EnumSet.allOf(clzz))
m.put(((OrdinalEnum)e).getVal(), (E)e);
return m;
}
}
In Kotlin:
enum class Status(val id: Int) {
NEW(0), VISIT(1), IN_WORK(2), FINISHED(3), CANCELLED(4), DUMMY(5);
companion object {
private val statuses = Status.values().associateBy(Status::id)
fun getStatus(id: Int): Status? = statuses[id]
}
}
Usage:
val status = Status.getStatus(1)!!
A good option is to avoid conversion from int to enum: for example, if you need the maximal value, you may compare x.ordinal() to y.ordinal() and return x or y correspondingly. (You may need to re-order you values to make such comparison meaningful.)
If that is not possible, I would store MyEnum.values() into a static array.
This is the same answer as the doctors but it shows how to eliminate the problem with mutable arrays. If you use this kind of approach because of branch prediction first if will have very little to zero effect and whole code only calls mutable array values() function only once. As both variables are static they will not consume n * memory for every usage of this enumeration too.
private static boolean arrayCreated = false;
private static RFMsgType[] ArrayOfValues;
public static RFMsgType GetMsgTypeFromValue(int MessageID) {
if (arrayCreated == false) {
ArrayOfValues = RFMsgType.values();
}
for (int i = 0; i < ArrayOfValues.length; i++) {
if (ArrayOfValues[i].MessageIDValue == MessageID) {
return ArrayOfValues[i];
}
}
return RFMsgType.UNKNOWN;
}
enum MyEnum {
A(0),
B(1);
private final int value;
private MyEnum(int val) {this.value = value;}
private static final MyEnum[] values = MyEnum.values();//cache for optimization
public static final getMyEnum(int value) {
try {
return values[value];//OOB might get triggered
} catch (ArrayOutOfBoundsException e) {
} finally {
return myDefaultEnumValue;
}
}
}

Categories

Resources