I am working with some existing code in my Eclipse project. In the method below called cardTypeForPbfValue(), I cannot find the key in the HashMap even though I can see it while debugging my the code. The pbfValueMap is populated as follows:
[1=ATM, 2=DEBIT, 3=CREDIT, 4=PAYROLL]
I'm not sure why I cannot get the associated value of CREDIT when I'm passing in a value of 3 in the cardTypeForPbfValue() below. I am actually getting a value of NULL.
Any help/direction would be appreciated.
Here is the code I'm working with:
public static enum CardType {
CREDIT(3),
ATM(1),
DEBIT(2),
PAYROLL(4);
CardType(int pbfValue) {
this.pbfValue = (short) pbfValue;
}
public static HashMap<Short, CardType> pbfValueMap = new HashMap<Short, CardType>();
static {
for (CardType cardType : CardType.values()) {
short value = cardType.pbfValue;
pbfValueMap.put(cardType.pbfValue, cardType);
}
}
public static CardType **cardTypeForPbfValue**(int pbfValue) {
CardType returnValue = pbfValueMap.get(pbfValue);
if (returnValue == null) {
returnValue = DEBIT;
}
return returnValue;
}
public short pbfValue;
}
You're looking up an Integer, but you put a Short into the map. Try this:
public static CardType cardTypeForPbfValue(int pbfValue) {
Short shortPbfValue = (short) pdbValue;
CardType returnValue = pbfValueMap.get(shortPbfValue);
...
}
Better yet, stop using int everywhere (or stop using short for the map) - just be consistent in the type that you want to use.
What I guess is that you are using Short as the key type whereas, you are looking for the value in HashMap with Integer key.That's why you are not getting the associated value for the entered key. To solve this your cardTypeForPbfValue method should be like this:
public static CardType cardTypeForPbfValue(short pbfValue)
And wherever, you call the method cardTypeForPbfValue pass the argument of type short to it. For example:
short s = 1;
CardType cType = cardTypeForPbfValue(s);
Related
I am passing few values to mail method for sending the details like below
private static String getTeam(String Team, List<String> prioritys1, String number,String description
) {
StringBuilder builder1 = new StringBuilder();
for (String v : prioritys1) {
if ( v == "1") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
else
if ( v == "3") {
Integer cnt1 = count1.get(new Team(Team, v,number,description));
if (cnt1 == null) {
cnt1 = 0;
}
else
if (cnt1 !=0){
cnt1 = 1;
mail1(Team,v,number,description);
}}
}
return builder1.toString();
}
I tried to store in arrays but it didnt worked.
I after pass above parameters, i need to store the value of the number. i need to store the number so that next time while passing the parameters i need to check first whether the number is already passed or not if not then only i need to pass to mail.
can any one help on this
With this code very complicated understand what you are doing. But if you need check value that already been processed store it outside of the method. Create global class variable:
public class className {
private final List<String> ARRAY = new ArrayList<>(); // global variable
public void yourMethod(String value) {
if (!ARRAY.contains(value)) {
mail(value);
ARRAY.add(value);
}
}
}
I dont know your case and I can not get better example.
You need to store the value in a "class level" variable. Whether the variable type needs to be static or instance will depend on your implementation of the method.
If you can post a sample code, we can help further.
You need to compare with 2 equals and not 1
Instead of
if( Team = A )
you need this way
if( Team == A )
Using Team = A, your saying that every time your code reaches that line it will equal Team to A.
Is it possible to use an enumeration in the following circumstance:
Let’s say you have a certain amount of predefined 'read types'. Example read types could be: Diagnostic, KWH, MaxDemand, OnPeak, etc. And for each of these read types, there’s a ‘TIMTagNumber’ which is essientally a protocol for retrieving each predefined read type.
For example, TIMTagNumber 1100 would retrieve the read type Diagnostic
TIMTagNumber 1300 would retrieve the read type KWH.
The problem is that a predefined read type can sometimes be retrieved by more than one TIMTagNumber.
I want to create an enumeration ReadType that would define each read type and all TIMTagNumbers that can be used to retrieve that read.
Can you use an enumeration in this way?
public enum ReadType{
KWH(1300)
Diagnostic(1100)
ReadType3(1400, 1401) // This read can be retrieved by both 1400 and 1401
}
If an enumeration is not the way to go, is there an elegant or efficient way to define these read types? The overall desired outcome of all this essientally is being recognizing what type of read it is based on the TIMTagNumbers.
I.E. Given 1400 OR 1401 you would know that it's 'ReadType3'.
Can you do this? Yes. Whether it's the right decision will depend on whether you want to couple these TIMTagNumbers to the read type. If not, a simple Map<Integer, ReadType> will probably suffice.
Here's how you could do it:
public static enum MyEnum {
KWH(1300),
Diagnostic(1100),
ReadType3(1400, 1401);
private Set<Integer> timTagNumbers;
MyEnum(Integer... timTagNumbers) {
this.timTagNumbers = new HashSet<Integer>(Arrays.asList(timTagNumbers));
//add check to make sure that values are unique across all instances
}
public static MyEnum forTIMTagNumber(int num) {
for ( MyEnum readType : values() ) {
if ( readType.timTagNumbers.contains(num) ) {
return readType;
}
}
throw new NoSuchElementException("No ReadType matching TIMTagNumber " + num);
}
}
//...
int timTagNumber = 1400;
ReadType readType = ReadType.forTIMTagNumber(timTagNumber);
As I said above, this style works well when the data and the enum types are intrinsically coupled already. It would not be good for when the enum type is decoupled from the mapped values (e.g. the values are used for one of many ways of serializing the enum) or if the values are configuration-specific or even dynamic (e.g. if they were prices on an item). In these cases it is usually best to externalize this mapping in an EnumMap or Map.
public enum ReadType {
KWH(1300),
Diagnostic(1100),
ReadType3(1400, 1401);
private int[] timTagNumbers;
private ReadType(int ... numbers) {
this.timTagNumbers = numbers;
}
public int[] getTimTagNumbers() {
return timTagNumbers;
}
public static ReadType forTimTagNumber(int n) {
for (ReadType type : values()) {
if (Arrays.binarySearch(type.timTagNumbers, n) != -1) {
return type;
}
}
throw new NoSucheElementException(); // if not found
}
With this you can do
int[] timTagNumbers = ReadType.Diagnostic.getTimTagNumbers(); // [ 1100 ]
and
ReadType type3 = ReadType.forTimTagNumber(1401); // ReadType.ReadType3
You can indeed use enumerations in that way, but your example is missing a private field and a constructor.
Something like:
public enum Bla{
CASE1(100),CASE2(200);
private int amount;
private Bla(int amount) {
this.amount = amount;
}
public Bla getByValue(int value){
switch (value) {
case 100: return CASE1;
case 200: return CASE2;
}
return null;
}
}
I've included a "reverse lookup" method that returns an Enum given the value.
The main advantage is that you can have the rest of your code using "Bla" instead of int's which will guarantee type-safety on your operations, basically, it'll make impossible to pass an invalid int value as a method parameter (and you can use switch statements over enums too, and that's pretty awesome in some usage scenarios).
EDIT: I noticed after I posted that you need more then one int to specify the Enum, but the same logic applies, with the due changes in the methods, of course.
You could do something like the following, when you supply values in the parentheses where the enum variable is declared, it is calling the constructor of the enum. You need to create a different method in the enum itself to get the enum type from the integer value. See below.
public enum ReadType {
KWH(), DIAGNOSTIC(), READTYPE3();
public ReadType getReadType(int num) {
ReadType toReturn = KWH;
switch (num) {
case 1300:
toReturn = KWH;
break;
case 1100:
toReturn = DIAGNOSTIC;
break;
case 1400:
toReturn = READTYPE3;
break;
case 1401:
toReturn = READTYPE3;
break;
}
return toReturn;
}
If you can impose some restrictions like no more than 2 tags can be associated with a read type and each tag is no greater than 2^15, then you can store the two numbers into 1 integer. See this S/O post for more details.
I have some enums like this:
public enum Classification {
UNKNOWN("Unknown"),
DELETION("Deletion"),
DUPLICATION("Duplication"), ....
but some of them have like 20 members, so currently in code I deal with them with huge if/else blocks like this:
int classification= rs.getInt("classification");
if (classification == Classification.UNKNOWN.ordinal()) {
variant.setClassification(Classification.UNKNOWN);
} else if (classification == Classification.DELETION.ordinal()) {
variant.setClassification(Classification.DELETION);
( rs is from JDBC tho).
Does Java have a better way this these big if/else blocks to do what I am doing? some sorting of looping through it?
You could use Enum#values() to get all enum values in an array. The ordinal maps 1:1 to the array index. Add the following method fo your Classification enum:
public static Classification of(int ordinal) {
if (0 <= ordinal && ordinal < values().length) {
return values()[ordinal];
}
throw new IllegalArgumentException("Invalid ordinal " + ordinal);
}
and use it as follows
Classification classification = Classification.of(rs.getInt("classification"));
// ...
However, using enum's ordinal for this is not the best practice. What if some developer rearranges the enum's values or adds/removes values? Even the javadoc warns that it has usually no use for developers. Rather give each enum value a fixed identifier. You could pass it in as an additional argument of the enum constructor argument. You could even use enum's String representation for that.
UNKNOWN(1, "Unknown"),
DELETION(2, "Deletion"),
DUPLICATION(3, "Duplication"),
// ...
Then use that value for DB instead and modify the of() method to walk through them in a foreach loop:
public static Classification of(int id) {
for (Classification classification : values()) {
if (classification.id == id) {
return classification;
}
}
throw new IllegalArgumentException("Invalid id " + id);
}
If the db value is the ordinal of the Enum then:
int classification= rs.getInt("classification");
variant.setClassification(Classification.values()[classification]);
I'll leave bounds checking as an exercise for the reader.
You can loop through an enumeration’s values via the object the someEnum.values() method returns:
for (Classification clz : Classification.values()) doSomethingWith(clz);
found here
I don’t know how exactly I can help you, since i don’t know what rs.getInt(String) does.
It seems to give back an Integer representing a enum value of Classification, but why?
Use variant.setClassification(YourEnumClassHere.values()[classification]). Enum.values() returns an array of all the declared enums in that class.
Instead of storing ordinal, you can store the name and use the valueOf method to convert the String back to your Enum type.
If you willing and able to store a string representation (this is a good technique) of the ENUM in your database, see Reference from Gareth Davis in comments above. If you are unwilling and/or unable to store a string representation and must continue with an ordinal representation, I suggest that a Map is called for. Here is some example code:
public class EnumMap
{
private enum FistSounds
{
Blam, Kapow, Zowie, Biff;
private static Map<Integer, FistSounds> ordinalMap = new HashMap<Integer, FistSounds>();
static
{
ordinalMap.put(Blam.ordinal(), Blam);
ordinalMap.put(Kapow.ordinal(), Kapow);
ordinalMap.put(Zowie.ordinal(), Zowie);
ordinalMap.put(Biff.ordinal(), Biff);
}
public static final FistSounds getByOrdinal(final int enumIndex)
{
return ordinalMap.get(enumIndex);
}
}
public static void main(String[] args)
{
FistSounds fistSound;
for (int index = -1; index < 5; ++index)
{
fistSound = FistSounds.getByOrdinal(index);
System.out.print("Ordinal: ");
System.out.print(index);
System.out.print(", FistSound: ");
System.out.println(fistSound);
}
}
}
I'd recommend using a switch statement, if the logic to execute is different for each case....
do as #Gareth Davis instructs and then just have a switch statement and handle each case as required.
Enums are also eligible to be used in switch statements see here
Can Any help me and Check my answer
(a) Declare a private instance variable (Attribute) called HouseMap which should hold an unsorted map with integer keys and string values.
Private Map< Integer, String> HouseMap = new HashMap<Integer, String>();
(b) Write a zero-argument constructor of HouseCatalogue that initializes HouseMap to an empty map.
houseMap = new HashMap<Integer, String>();
(c) Write an instance method called addHouse() for the HouseCatalogue class that takes no arguments, and returns no value. This method should simply enter the four entries shown above into the HouseMap.
Public void addHouse()
{
HouseMap.put(101," adison Sas") ;
HouseMap.put(103," FourSeasons") ;
HouseMap.put(105," Hayat Regency ");
HouseMap.put(107," Concord al-Salam ") ;
}
(d) Write an instance method called printHouse() for the HouseCatalogue class that takes an integer argument, and return a string value. This method should print the value (House name) of the area code that is equal to integer argument and return it. Otherwise it will return null.
Public string printHouse( int area)
{
for(Integer eachcode : HouseMap.keySet())
{
if ( HouseMap.keySet()== area)
{
System.out.println("House name is"+ HouseMap.get(eachcode));
}
}
}
or
public static void printHouse( int area)
{
for(Map.Entry<Integer,String> entry : houseMap.entrySet())
{
if (entry.getKey().equals(area))
{
System.out.println("House name is"+ entry.getValue());
//return entry.getValue(); // return it
}
}
}
(a) Lower case letter for private and no new HashMap() needed when declaring. Normally when useing java convensions you use camelcase when declaring your variasbles (houseMap) but it's fine.
private Map<Integer, String> HouseMap;
(b) You have declared your variable with HouseMap not houseMap (see (a) camelcase) so initializing it needs the same variable:
HouseMap = new HashMap<Integer, String>();
(c) Seems fine
(d) Hum, don't see the point in the method, it should both print the value and return it.. well.. first off public lower case letters again, String with a big letter (name of the class` and then the implementation:
public String printHouse(int area) {
if (HouseMap.containsKey(area)) {
String name = HouseMap.get(area);
System.out.println("The house with the area code " + area +
" is " + name));
return name;
}
return null;
}
a) only declare the variable - do not initialize it
b) ok
c) ok
d) in a map you have random access. look at Map#get(Integer) API. you don't need to iterate over the entry set
Since the key of a map is unique, you can simplify the last method as follows:
public static void printHouse( int area)
{
String name = houseMap.get(area); // May return null
System.out.println("House name is " + name);
return name;
}
public and private must be written with a lowercase p everywhere.
You should show the entire constructor, not just the code that goes in it.
Fix your indentation. Use the same amount of indentation for every level, and make sure that everything lines up neatly.
When you use a foreach loop like for (Integer eachcode: HouseMap.keySet()), the iteration variable is eachcode. This is the value that you should compare to area, because that's what the integer is. You don't want to compare the supplied to all of the area codes taken as a single unit (those aren't the same kind of thing); you want to compare it to each area code in turn.
But you don't want to write that loop at all. The point of a HashMap is to let you look up the value, given the key. That is what .get() does. You have the key: it is area. So all you need to do is look it up: System.out.println("House name is " + HouseMap.get(area)).
You also need to return the name that you looked up, not just print it, and you need to check that the name is there (use .contains()) before printing.
It looks like somebody else commented your code to say "you also forgot to return it". Did you try talking to this person, or reading the comments?
Just a hint for the last one:
(d) Write an instance method called
An instance method is not a static method, you have to remove the static keyword in your second (d) method...
Thanks alot for every body
public static String printHouse(int
code) {
if (houseMap.containsKey(code))
{
String name = houseMap.get(coe);
System.out.println(code+ " : " + name);
return name;
} else{
System.out.println("null");
return null; }
I've the enum type ReportTypeEnum that get passed between methods in all my classes but I then need to pass this on the URL so I use the ordinal method to get the int value. After I get it in my other JSP page, I need to convert it to back to an ReportTypeEnum so that I can continue passing it.
How can I convert ordinal to the ReportTypeEnum?
Using Java 6 SE.
To convert an ordinal into its enum representation you might want to do this:
ReportTypeEnum value = ReportTypeEnum.values()[ordinal];
Please notice the array bounds.
Note that every call to values() returns a newly cloned array which might impact performance in a negative way. You may want to cache the array if it's going to be called often.
Code example on how to cache values().
This answer was edited to include the feedback given inside the comments
This is almost certainly a bad idea. Certainly if the ordinal is de-facto persisted (e.g. because someone has bookmarked the URL) - it means that you must always preserve the enum ordering in future, which may not be obvious to code maintainers down the line.
Why not encode the enum using myEnumValue.name() (and decode via ReportTypeEnum.valueOf(s)) instead?
If I'm going to be using values() a lot:
enum Suit {
Hearts, Diamonds, Spades, Clubs;
public static final Suit values[] = values();
}
Meanwhile wherever.java:
Suit suit = Suit.values[ordinal];
If you want the array to be private, be my guest:
private static final Suit values[] = values();
public static Suit get(int ordinal) { return values[ordinal]; }
...
Suit suit = Suit.get(ordinal);
Mind your array bounds.
I agree with most people that using ordinal is probably a bad idea. I usually solve this problem by giving the enum a private constructor that can take for example a DB value then create a static fromDbValue function similar to the one in Jan's answer.
public enum ReportTypeEnum {
R1(1),
R2(2),
R3(3),
R4(4),
R5(5),
R6(6),
R7(7),
R8(8);
private static Logger log = LoggerFactory.getLogger(ReportEnumType.class);
private static Map<Integer, ReportTypeEnum> lookup;
private Integer dbValue;
private ReportTypeEnum(Integer dbValue) {
this.dbValue = dbValue;
}
static {
try {
ReportTypeEnum[] vals = ReportTypeEnum.values();
lookup = new HashMap<Integer, ReportTypeEnum>(vals.length);
for (ReportTypeEnum rpt: vals)
lookup.put(rpt.getDbValue(), rpt);
}
catch (Exception e) {
// Careful, if any exception is thrown out of a static block, the class
// won't be initialized
log.error("Unexpected exception initializing " + ReportTypeEnum.class, e);
}
}
public static ReportTypeEnum fromDbValue(Integer dbValue) {
return lookup.get(dbValue);
}
public Integer getDbValue() {
return this.dbValue;
}
}
Now you can change the order without changing the lookup and vice versa.
You could use a static lookup table:
public enum Suit {
spades, hearts, diamonds, clubs;
private static final Map<Integer, Suit> lookup = new HashMap<Integer, Suit>();
static {
int ordinal = 0;
for (Suit suit : EnumSet.allOf(Suit.class)) {
lookup.put(ordinal, suit);
ordinal+= 1;
}
}
public Suit fromOrdinal(int ordinal) {
return lookup.get(ordinal);
}
}
This is what I use. I make no pretense that it's far less "efficient" than the simpler solutions above. What it does do is provide a much clearer exception message than "ArrayIndexOutOfBounds" when an invalid ordinal value is used in the solution above.
It utilizes the fact that EnumSet javadoc specifies the iterator returns elements in their natural order. There's an assert if that's not correct.
The JUnit4 Test demonstrates how it's used.
/**
* convert ordinal to Enum
* #param clzz may not be null
* #param ordinal
* #return e with e.ordinal( ) == ordinal
* #throws IllegalArgumentException if ordinal out of range
*/
public static <E extends Enum<E> > E lookupEnum(Class<E> clzz, int ordinal) {
EnumSet<E> set = EnumSet.allOf(clzz);
if (ordinal < set.size()) {
Iterator<E> iter = set.iterator();
for (int i = 0; i < ordinal; i++) {
iter.next();
}
E rval = iter.next();
assert(rval.ordinal() == ordinal);
return rval;
}
throw new IllegalArgumentException("Invalid value " + ordinal + " for " + clzz.getName( ) + ", must be < " + set.size());
}
#Test
public void lookupTest( ) {
java.util.concurrent.TimeUnit tu = lookupEnum(TimeUnit.class, 3);
System.out.println(tu);
}
Safety first (with Kotlin):
// Default to null
EnumName.values().getOrNull(ordinal)
// Default to a value
EnumName.values().getOrElse(ordinal) { EnumName.MyValue }
This is what I do on Android with Proguard:
public enum SomeStatus {
UNINITIALIZED, STATUS_1, RESERVED_1, STATUS_2, RESERVED_2, STATUS_3;//do not change order
private static SomeStatus[] values = null;
public static SomeStatus fromInteger(int i) {
if(SomeStatus.values == null) {
SomeStatus.values = SomeStatus.values();
}
if (i < 0) return SomeStatus.values[0];
if (i >= SomeStatus.values.length) return SomeStatus.values[0];
return SomeStatus.values[i];
}
}
it's short and I don't need to worry about having an exception in Proguard
You can define a simple method like:
public enum Alphabet{
A,B,C,D;
public static Alphabet get(int index){
return Alphabet.values()[index];
}
}
And use it like:
System.out.println(Alphabet.get(2));
public enum Suit implements java.io.Serializable, Comparable<Suit>{
spades, hearts, diamonds, clubs;
private static final Suit [] lookup = Suit.values();
public Suit fromOrdinal(int ordinal) {
if(ordinal< 1 || ordinal> 3) return null;
return lookup[value-1];
}
}
the test class
public class MainTest {
public static void main(String[] args) {
Suit d3 = Suit.diamonds;
Suit d3Test = Suit.fromOrdinal(2);
if(d3.equals(d3Test)){
System.out.println("Susses");
}else System.out.println("Fails");
}
}
I appreciate that you share with us if you have a more efficient code, My enum is huge and constantly called thousands of times.
So one way is to doExampleEnum valueOfOrdinal = ExampleEnum.values()[ordinal]; which works and its easy, however,
as mentioned before, ExampleEnum.values() returns a new cloned array for every call. That can be unnecessarily expensive. We can solve that by caching the array like so ExampleEnum[] values = values(). It is also "dangerous" to allow our cached array to be modified. Someone could write ExampleEnum.values[0] = ExampleEnum.type2; So I would make it private with an accessor method that does not do extra copying.
private enum ExampleEnum{
type0, type1, type2, type3;
private static final ExampleEnum[] values = values();
public static ExampleEnum value(int ord) {
return values[ord];
}
}
You would use ExampleEnum.value(ordinal) to get the enum value associated with ordinal
There is an Easy and Bad way and there is a fairly easy and right way.
First, the easy and bad (those are usually very popular). Enum class method returns an array of all available instances via the values() method and you can access the enum object via array index.
RenderingMode mode = RenderingMode.values()[index];
//Enum Class somewhere else
public enum RenderingMode
{
PLAYING,
PREVIEW,
VIEW_SOLUTION;
}
//RenderingMode.values()[0] will return RenderingMode.PLAYING
//RenderingMode.values()[1] will return RenderingMode.PREVIEW
//Why this is bad? Because it is linked to order of declaration.
//If you later changed the order here, it will impact all your existing logic around this.
public enum RenderingMode
{
PREVIEW,
VIEW_SOLUTION,
PLAYING;
}
//Now
//RenderingMode.values()[0] will return RenderingMode.PREVIEW
//RenderingMode.values()[1] will return RenderingMode.VIEW_SOLUTION
Here is the right way to do it.
Create a static method fromInt in your enum class.
public enum RenderingMode
{
PLAYING,
PREVIEW,
VIEW_SOLUTION;
public static RenderingModefromInt(int index)
{
//this is independent of order of declaration
switch (index)
{
case 0: return PLAYING;
case 1: return PREVIEW;
case 2: return VIEW_SOLUTION;
}
//Consider throwing Exception here
return null;
}
}
public enum Status {
STATUS_1, STATUS_2, STATUS_3, STATUS_4;
public static Status getStatusByOrdinal(int ordinal) {
for (Status status : values()) {
if (status.ordinal() == ordinal) {
return status;
}
}
return STATUS_1;
}
}
In this way you can not depend on compile-time generics resolution(so having an enum class instance you can create whenever enum you want, even those types created with Class.forMame)
public Object getInstance(Class enumClazz, int ordinal) throws Exception {
Object[] allEnums = enumClazz.getDeclaredMethod("values", Object[].class).invoke(null, null);
return allEnums[ordinal];
}
Every enum has name(), which gives a string with the name of enum member.
Given enum Suit{Heart, Spade, Club, Diamond}, Suit.Heart.name() will give Heart.
Every enum has a valueOf() method, which takes an enum type and a string, to perform the reverse operation:
Enum.valueOf(Suit.class, "Heart") returns Suit.Heart.
Why anyone would use ordinals is beyond me. It may be nanoseconds faster, but it is not safe, if the enum members change, as another developer may not be aware some code is relying on ordinal values (especially in the JSP page cited in the question, network and database overhead completely dominates the time, not using an integer over a string).