I've an enum like this:
public enum PcapLinkType {
DLT_NULL(0)
DLT_EN10MB(1)
DLT_EN3MB(2),
DLT_AX25(3),
/*snip, 200 more enums, not always consecutive.*/
DLT_UNKNOWN(-1);
private final int value;
PcapLinkType(int value) {
this.value= value;
}
}
Now I get an int from external input and want the matching input - throwing an exception if a value does not exist is ok, but preferably I'd have it be DLT_UNKNOWN in that case.
int val = in.readInt();
PcapLinkType type = ???; /*convert val to a PcapLinkType */
You would need to do this manually, by adding a a static map in the class that maps Integers to enums, such as
private static final Map<Integer, PcapLinkType> intToTypeMap = new HashMap<Integer, PcapLinkType>();
static {
for (PcapLinkType type : PcapLinkType.values()) {
intToTypeMap.put(type.value, type);
}
}
public static PcapLinkType fromInt(int i) {
PcapLinkType type = intToTypeMap.get(Integer.valueOf(i));
if (type == null)
return PcapLinkType.DLT_UNKNOWN;
return type;
}
There's a static method values() which is documented, but not where you'd expect it: http://docs.oracle.com/javase/tutorial/java/javaOO/enum.html
enum MyEnum {
FIRST, SECOND, THIRD;
private static MyEnum[] allValues = values();
public static MyEnum fromOrdinal(int n) {return allValues[n];}
}
In principle, you can use just values()[i], but there are rumors that values() will create a copy of the array each time it is invoked.
You will have to make a new static method where you iterate PcapLinkType.values() and compare:
public static PcapLinkType forCode(int code) {
for (PcapLinkType typŠµ : PcapLinkType.values()) {
if (type.getValue() == code) {
return type;
}
}
return null;
}
That would be fine if it is called rarely. If it is called frequently, then look at the Map optimization suggested by others.
if you have enum like this
public enum PcapLinkType {
DLT_NULL(0)
DLT_EN10MB(1)
DLT_EN3MB(2),
DLT_AX25(3),
DLT_UNKNOWN(-1);
private final int value;
PcapLinkType(int value) {
this.value= value;
}
}
then you can use it like
PcapLinkType type = PcapLinkType.values()[1]; /*convert val to a PcapLinkType */
You can do something like this to automatically register them all into a collection with which to then easily convert the integers to the corresponding enum. (BTW, adding them to the map in the enum constructor is not allowed. It's nice to learn new things even after many years of using Java. :)
public enum PcapLinkType {
DLT_NULL(0),
DLT_EN10MB(1),
DLT_EN3MB(2),
DLT_AX25(3),
/*snip, 200 more enums, not always consecutive.*/
DLT_UNKNOWN(-1);
private static final Map<Integer, PcapLinkType> typesByValue = new HashMap<Integer, PcapLinkType>();
static {
for (PcapLinkType type : PcapLinkType.values()) {
typesByValue.put(type.value, type);
}
}
private final int value;
private PcapLinkType(int value) {
this.value = value;
}
public static PcapLinkType forValue(int value) {
return typesByValue.get(value);
}
}
I know this question is a few years old, but as Java 8 has, in the meantime, brought us Optional, I thought I'd offer up a solution using it (and Stream and Collectors):
public enum PcapLinkType {
DLT_NULL(0),
DLT_EN3MB(2),
DLT_AX25(3),
/*snip, 200 more enums, not always consecutive.*/
// DLT_UNKNOWN(-1); // <--- NO LONGER NEEDED
private final int value;
private PcapLinkType(int value) { this.value = value; }
private static final Map<Integer, PcapLinkType> map;
static {
map = Arrays.stream(values())
.collect(Collectors.toMap(e -> e.value, e -> e));
}
public static Optional<PcapLinkType> fromInt(int value) {
return Optional.ofNullable(map.get(value));
}
}
Optional is like null: it represents a case when there is no (valid) value. But it is a more type-safe alternative to null or a default value such as DLT_UNKNOWN because you could forget to check for the null or DLT_UNKNOWN cases. They are both valid PcapLinkType values! In contrast, you cannot assign an Optional<PcapLinkType> value to a variable of type PcapLinkType. Optional makes you check for a valid value first.
Of course, if you want to retain DLT_UNKNOWN for backward compatibility or whatever other reason, you can still use Optional even in that case, using orElse() to specify it as the default value:
public enum PcapLinkType {
DLT_NULL(0),
DLT_EN3MB(2),
DLT_AX25(3),
/*snip, 200 more enums, not always consecutive.*/
DLT_UNKNOWN(-1);
private final int value;
private PcapLinkType(int value) { this.value = value; }
private static final Map<Integer, PcapLinkType> map;
static {
map = Arrays.stream(values())
.collect(Collectors.toMap(e -> e.value, e -> e));
}
public static PcapLinkType fromInt(int value) {
return Optional.ofNullable(map.get(value)).orElse(DLT_UNKNOWN);
}
}
As #MeBigFatGuy says, except you can make your static {...} block use a loop over the values() collection:
static {
for (PcapLinkType type : PcapLinkType.values()) {
intToTypeMap.put(type.getValue(), type);
}
}
You could add a static method in your enum that accepts an int as a parameter and returns a PcapLinkType.
public static PcapLinkType of(int linkType) {
switch (linkType) {
case -1: return DLT_UNKNOWN
case 0: return DLT_NULL;
//ETC....
default: return null;
}
}
This is what I use:
public enum Quality {ENOUGH,BETTER,BEST;
private static final int amount = EnumSet.allOf(Quality.class).size();
private static Quality[] val = new Quality[amount];
static{ for(Quality q:EnumSet.allOf(Quality.class)){ val[q.ordinal()]=q; } }
public static Quality fromInt(int i) { return val[i]; }
public Quality next() { return fromInt((ordinal()+1)%amount); }
}
static final PcapLinkType[] values = { DLT_NULL, DLT_EN10MB, DLT_EN3MB, null ...}
...
public static PcapLinkType getPcapLinkTypeForInt(int num){
try{
return values[int];
}catch(ArrayIndexOutOfBoundsException e){
return DLT_UKNOWN;
}
}
This might not be a great solution, but its working for me:
public enum Type {
WATER, FIRE, GRASS;
public static Type getType(int value){
if(value==WATER.ordinal()){
return WATER;
}else if(value==FIRE.ordinal()){
return FIRE;
}else if(value==GRASS.ordinal()){
return GRASS;
}else {
return null;
}
}
}
There is no way to elegantly handle integer-based enumerated types. You might think of using a string-based enumeration instead of your solution. Not a preferred way all the times, but it still exists.
public enum Port {
/**
* The default port for the push server.
*/
DEFAULT("443"),
/**
* The alternative port that can be used to bypass firewall checks
* made to the default <i>HTTPS</i> port.
*/
ALTERNATIVE("2197");
private final String portString;
Port(final String portString) {
this.portString = portString;
}
/**
* Returns the port for given {#link Port} enumeration value.
* #return The port of the push server host.
*/
public Integer toInteger() {
return Integer.parseInt(portString);
}
}
Related
I'm looking for nice syntax for providing a default value in the case of null. I've been used to using Optional's instead of null in Java where API's are concerned, and was wondering if C#'s nicer nullable types have an equivalent?
Optionals
Optional<String> x = Optional<String>.absent();
String y = x.orElse("NeedToCheckforNull"); //y = NeedToCheckforNull
#nullable
String x = null;
String y = x == null ? "NeedToCheckforNull" : x ; //y = NeedToCheckforNull
How would I make the above more readable in C#?
JavaScript would allow y = x | "NeedToCheckforNull"
You can use the ?? operator.
Your code will be updated to:
string x = null;
string y = x ?? "NeedToCheckforNull";
See: ?? Operator (C# Reference)
C# has the special Nullable<T> type which can be declared with int?, decimal?, etc. These can provide a default value by using .GetValueOrDefault(), T GetValueOrDefault(T defaultValue), and the ?? operator.
string x = null;
Console.WriteLine(x ?? "NeedToCheckforNull");
.Net developers always try to compare C# feature to java. This is their big mistake. Microsoft always teach them like that. But they don't know how java capable of. Optional is not only nullable type. Nullable type is one of the its feature. But main purpose of Optional is single stream. You can use map(), flatMap() and filter() Lambda expression functions. There is no such alternative in .Net world unfortunately.
However there is lambda expression on List if you want to use as Optional.
But for single item, there is not such feature in .Net
I've created my own.
public class Optional<T> {
private T value;
public bool IsPresent { get; private set; } = false;
private Optional() { }
public static Optional<T> Empty() {
return new Optional<T>();
}
public static Optional<T> Of(T value) {
Optional<T> obj = new Optional<T>();
obj.Set(value);
return obj;
}
public void Set(T value) {
this.value = value;
IsPresent = true;
}
public T Get() {
return value;
}
}
consider using language extensions option type
int x = optional.IfNone("NeedToCheckforNull");
Thanks for the inspiration #sm-adnan
using System;
using System.Diagnostics.CodeAnalysis;
namespace Common;
public readonly struct Optional<T>
{
private readonly T _value;
private Optional(T value)
{
_value = value;
}
public static Optional<T> Empty() => new Optional<T>(default);
public static Optional<T> Of([AllowNull] T value)
{
return value is null ? Empty() : new Optional<T>(value);
}
public T GetValue()
{
if (HasValue()) return _value;
throw new InvalidOperationException("No value present");
}
public bool HasValue()
{
return _value is not null;
}
public void HasValue(Action<T> method)
{
if (HasValue()) method.Invoke(_value);
}
public void HasValue(Func<object> method)
{
if (HasValue()) method.Invoke();
}
public T OrElse(T other)
{
return HasValue() ? _value : other;
}
public T OrElseGet(Func<T> method)
{
return HasValue() ? _value : method.Invoke();
}
public T OrElseThrow(Func<Exception> method)
{
return HasValue() ? _value : throw method.Invoke();
}
public Optional<TU> Map<TU>(Func<T, TU> method)
{
return HasValue() ? new Optional<TU>(method.Invoke(_value)) : default;
}
}
How can I return enums like this?
Before I was returing an int with 0 if no, 1 if yes and 2 if other. But this wasn't good way to do. So how should it be done. My code:
class SomeClass{
public enum decizion{
YES, NO, OTHER
}
public static enum yourDecizion(){
//scanner etc
if(x.equals('Y')){
return YES;
}
else if (x.equals('N')){
return NO;
}
else{
return OTHER;
}
}
}
I don't what the "//scanner etc." does, but the methods return type should be decizion:
public static decizion yourDecizion() { ... }
Furthermore, you can add the Y, N, etc. values to the enum constants:
public enum decizion{
YES("Y"), NO("N"), OTHER;
String key;
decizion(String key) { this.key = key; }
//default constructor, used only for the OTHER case,
//because OTHER doesn't need a key to be associated with.
decizion() { }
static decizion getValue(String x) {
if ("Y".equals(x)) { return YES; }
else if ("N".equals(x)) { return NO; }
else if (x == null) { return OTHER; }
else throw new IllegalArgumentException();
}
}
Then, in the method, you can just do:
public static decizion yourDecizion() {
...
String key = ...
return decizion.getValue(key);
}
I think you should do something like these, an enum class. Then you can add as many types you want and the method yourDecizion() will return the enum type depending on the given parameter.
public enum SomeClass {
YES(0),
NO(1),
OTHER(2);
private int code;
private SomeClass(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public static SomeClass yourDecizion(int x) {
SomeClass ret = null;
for (SomeClass type : SomeClass.values()) {
if (type.getCode() == x)
ret = type;
}
return ret;
}
}
Change your code to:
class SomeClass{
public enum decizion {
YES, NO, OTHER
}
public static decizion yourDecizion(){
//scanner etc
if(x.equals('Y')){
return decizion.YES;
}
else if (x.equals('N')){
return decizion.NO;
}
else{
return decizion.OTHER;
}
}
}
Note: The method return type must be decizion instead of enum and decizion should have an upper case name (as all classes should).
You can get the value in below way. Here you have private constructor which will initialize the value you want to set and when the instance method value gets invoked simply return this.key.
public class Application {
enum Day {
MONDAY("Monday"), TUESDAY("Tuesday");
String key;
Day(String str) {
key = str;
}
public String value() {
return this.key;
}
}
public static void main(String[] args) {
System.out.println(Day.MONDAY.value());
}
}
I'm trying to get the best way to implement a file with all my static enums, without using any getters and setters, just static info, I achieve this in PHP like in the example below, do you really need getters and setters in java?
final class EnumTrade {
const buy = 1;
const sell = 2;
}
final class EnumGender {
const male = 1;
const female = 2;
}
final class EnumHttpMethod {
const get = 1;
const post = 2;
}
public enum EnumTrade {
BUY, SELL
}
and so on.
Edit: If the number matters, do:
public enum EnumTrade {
BUY(1), SELL(2)
}
in java enum not necessary to have getter and setter these are used for normal POJO or beans
sample enum can be:
public enum EventRecurringType {
YEARLY("1"),
QUARTERLY("2"),
MONTHLY("3"),
WEEKLY("4"),
DAILY("5"),
NONE("0");
private String value;
EventRecurringType(String value) {
this.value = value;
}
public String getValue() {
return value;
}
#Override
public String toString() {
return this.getValue();
}
public static EventRecurringType getEnum(String value) {
if(value == null)
throw new IllegalArgumentException();
for(EventRecurringType v : values())
if(value.equalsIgnoreCase(v.getValue())) return v;
throw new IllegalArgumentException();
}
}
public enum EnumTrade
{
BUY,
SELL,
}
If all you need is the ordinal values of the enums, you can access those directly via EnumTrade.BUY.ordinal
If you want to store other data in the enum, do something like this (expanding as needed):
public enum EnumGender
{
MALE(1),
FEMALE(2);
private final int value;
private EnumGender(String value)
{
this.value = value;
}
public int getValue()
{
return this.value;
}
//In case you need to grab an enum by the value constant
public getEnumGender(int value)
{
switch(value)
{
case 1:
return EnumGender.MALE;
case 2:
default:
return EnumGender.FEMALE;
}
}
}
For sake of completeness and the fact answers pop in while writing i changed my original answer to mention you could store all your enums in one java class.
=> It is way better to have them stored in own files like user Tichodroma suggests
However translating your exmaple code you could build this in Java:
public class MyEnums {
public enum EnumTrade{
BUY, SELL
}
public enum EnumGender{
MALE, FEMALE
}
public enum EnumHttpMethod{
GET, POST
}
}
And then use the different enums from outside like this:
MyEnums.EnumTrade.BUY
public enum MyConst{ BUY(1), SELL(2), MALE(3), FEMALE(4), GET(5), POST(6);
public final int value;
MyConst(int value) {
this.value = value;
}
public int getValue() {
return value;
}
};
or Just go with
public enum MyConst{ BUY(1), SELL(2) }; and same for MALE, FEMALE ....
Previously, I had my LegNo enums defined simply as:
NO_LEG, LEG_ONE, LEG_TWO
and by calling return LegNo.values()[i];, I was able to get the value associated with each enum.
But now I've decided I want the LegNo enum NO_LEG to be the int -1 instead of 0
so I decided to use a private constructor to initialise and set its int value
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private LegNo(final int leg) { legNo = leg; }
the only thing now is that because I'm doing it this way the values() method will not work for the NO_LEG enum. How do I get the enum associated with the int? Is there any efficient way of doing this other than using a case switch statement or an if-elseif-elseif
I can see a lot of SO questions to do with getting the int value from the enum, but I'm after the reverse.
EDIT August 2018
Today I would implement this as follows
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private final int value;
LegNo(int value) {
this.value = value;
}
public static Optional<LegNo> valueOf(int value) {
return Arrays.stream(values())
.filter(legNo -> legNo.value == value)
.findFirst();
}
}
You'll have to maintain a mapping inside the enum.
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private int legNo;
private static Map<Integer, LegNo> map = new HashMap<Integer, LegNo>();
static {
for (LegNo legEnum : LegNo.values()) {
map.put(legEnum.legNo, legEnum);
}
}
private LegNo(final int leg) { legNo = leg; }
public static LegNo valueOf(int legNo) {
return map.get(legNo);
}
}
The static block will be invoked only once, so there is practically no performance issue here.
EDIT: Renamed the method to valueOf as it is more inline with other Java classes.
You could also include a static method in the enum that iterates through all members and returns the correct one.
public enum LegNo {
NO_LEG(-1),
LEG_ONE(1),
LEG_TWO(2);
private int legIndex;
private LegNo(int legIndex) { this.legIndex = legIndex; }
public static LegNo getLeg(int legIndex) {
for (LegNo l : LegNo.values()) {
if (l.legIndex == legIndex) return l;
}
throw new IllegalArgumentException("Leg not found. Amputated?");
}
}
Now, if you want to get an Enum value by the integer, you just use:
int myLegIndex = 1; //expected : LEG_ONE
LegNo myLeg = LegNo.getLeg(myLegIndex);
adarshr's answer adapted to Java 8:
import static java.util.Arrays.stream;
import static java.util.stream.Collectors.toMap;
import java.util.Map;
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private final int legNo;
private final static Map<Integer, LegNo> map =
stream(LegNo.values()).collect(toMap(leg -> leg.legNo, leg -> leg));
private LegNo(final int leg) {
legNo = leg;
}
public static LegNo valueOf(int legNo) {
return map.get(legNo);
}
}
You can also access Enum value corresponding to given integer value simply by calling values() method on enum LegNo. It returns field of LegNo enums:
LegNo.values()[0]; //returns LEG_NO
LegNo.values()[1]; //returns LEG_ONE
LegNo.values()[2]; //returns LEG_TWO
Not precisely the thing he was looking for, but pretty close though and very simple indeed. (Although the subject is dead it might be useful for someone else.)
Java 8 way with default value:
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private final int legNo;
LegNo(int legNo) {
this.legNo = legNo;
}
public static LegNo find(int legNo, Supplier<? extends LegNo> byDef) {
return Arrays.asList(LegNo.values()).stream()
.filter(e -> e.legNo == legNo).findFirst().orElseGet(byDef);
}
}
to call:
LegNo res = LegNo.find(0, () -> LegNo.NO_LEG);
or with Exception:
LegNo res = LegNo.find(0, () -> {
throw new RuntimeException("No found");
});
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private final int code;
LegNo(int code) {
this.code = code;
ReverseStorage.reverseMap.put(code, this);
}
public static Optional<LegNo> getByCode(int code) {
return Optional.ofNullable(ReverseStorage.reverseMap.get(code));
}
private static final class ReverseStorage {
private static final Map<Integer, LegNo> reverseMap = new LinkedHashMap<>();
}
}
Since your enum only contains 3 elements, the fastest way will be to just use a series of if else, like you suggested.
edit: the answer that adarshr provided is better suited for general cases, where there are many enum values, but I think it is an overkill for your problem.
public enum LegNo {
NO_LEG(-1), LEG_ONE(1), LEG_TWO(2);
private int legNo;
private LegNo(int leg) { legNo = leg; }
public static LegNo valueOf(int legNo) {
for (LegNo leg : LegNo.values()) {
if (leg.legNo == legNo) return leg;
}
}
}
assert LegNo.valueOf(2) == LegNo.LEG_TWO
assert LegNo.valueOf(3) == null
Given the following java enum:
public enum AgeRange {
A18TO23 {
public String toString() {
return "18 - 23";
}
},
A24TO29 {
public String toString() {
return "24 - 29";
}
},
A30TO35 {
public String toString() {
return "30 - 35";
}
},
}
Is there any way to convert a string value of "18 - 23" to the corresponding enum value i.e. AgeRange.A18TO23 ?
Thanks!
The best and simplest way to do it is like this:
public enum AgeRange {
A18TO23 ("18-23"),
A24TO29 ("24-29"),
A30TO35("30-35");
private String value;
AgeRange(String value){
this.value = value;
}
public String toString(){
return value;
}
public static AgeRange getByValue(String value){
for (final AgeRange element : EnumSet.allOf(AgeRange.class)) {
if (element.toString().equals(value)) {
return element;
}
}
return null;
}
}
Then you just need to invoke the getByValue() method with the String input in it.
You could always create a map from string to value - do so statically so you only need to map it once, assuming that the returned string remains the same over time. There's nothing built-in as far as I'm aware.
According to effective java (2nd ed) item 30, it can be (it is much faster than the loop)
public enum AgeRange {
A18TO23("18-23"),
A24TO29("24-29"),
A30TO35("30-35");
private final String value;
AgeRange(String value){
this.value = value;
}
#Override public String toString(){
return value;
}
private static final Map<String, AgeRange> stringToEnum =
new HashMap<String, AgeRange>();
static {
for (AgeRange r : values()) {
stringToEnum.put(r.toString(), r);
}
}
public static AgeRange getByValue(String value){
return stringToEnum.get(value);
}
}
for (AgeRange ar: EnumSet.allOf(AgeRange)) {
if (ar.toString().equals(inString)) {
myAnswer = ar;
break;
}
}
Or something like that? Just typed in, haven't run through a compiler. Forgive (comment on) typos...
Or use logic like this to build a map once. Avoid iteration at runtime. Good idea, Jon.
The class overrides "toString()" - so, to get the reverse operation, you need to override valueOf() to translate the output of toString() back to the Enum values.
public enum AgeRange {
A18TO23 {
public String toString() {
return "18 - 23";
}
public AgeRange valueOf (Class enumClass, String name) {
return A18T023
}
},
.
.
.
}
Buyer beware - uncompiled and untested...
The mechanism for toString() and valueOf() is a documented part of the API
You could try something like the following?
static AgeRange fromString(String range) {
for (AgeRange ageRange : values()) {
if (range.equals(ageRange.toString())) {
return ageRange;
}
}
return null;
}
Or, as others suggested, using a caching approach:
private static Map<String, AgeRange> map;
private static synchronized void registerAgeRange(AgeRange ageRange) {
if (map == null) {
map = new HashMap<String, AgeRange>();
}
map.put(ageRange.toString(), ageRange);
}
AgeRange() {
registerAgeRange(this);
}
static AgeRange fromString(String range) {
return map.get(range);
}