Setting values of enumerations, and parsing string to get an enum - java

My enum is like this currently:
public enum Manufacturers {
Honda,
GM,
Toyota,
Ferrari
}
I need to create a Hashmap so I plan on doing this, is this correct?
Manufacturers mfg = Manufacturers.Honda;
mfg.ordinal() // save as key
i.e. I will store the key using the enumInstance.ordinal()
Also, I need to be able to parse a string which will be the ordinal value of the enumeration, and get an enum back:
Manufacturers mfg = Manufacturers.valueOf(mfgOrdinalValueAsString);
The above gave me an error (the string was "1"). Is this the correct way? I guess I should have a try/catch in there right?

The .valueOf would actually be expecting the String "GM" (for 1).
As for storing your enum values in a map, use EnumMap which is designed specifically for this - and will be fast at it, too.
If you really wanted to reference a value by its ordinal, use something like Manufacturers.values()[1].

A suggestion: better use name() to get the name of the enum as a String, and whenever you need to get back the original Enum from it, use the valueOf() method - since valueOf() expects the name, not the ordinal, as a parameter. For example:
enum Example {ONE, TWO};
String name = Example.ONE.name();
Example e = Example.valueOf(Example.class, name); // e has value ONE
If you definitely need to use the ordinal, the ordinal() method will return an index which you can use to retrieve the respective Enum from the array returned by the values() method. Like this:
int ordinal = Example.ONE.ordinal();
Example e = Example.values()[ordinal]; // e has value ONE
As has already been pointed out, consider using EnumMap, as stated in the documentation, it is
A specialized Map implementation for use with enum type keys. All of the keys in an enum map must come from a single enum type that is specified, explicitly or implicitly, when the map is created. Enum maps are represented internally as arrays. This representation is extremely compact and efficient.
EDIT
If you need to associate a different code to each element of the enum (other than its automatically assigned ordinal), you can always add it as an attribute to the enum, together with getters and setters, like this:
public enum Manufacturers {
Honda(10),
GM(20),
Toyota(30),
Ferrari(40);
private int code;
Manufacturers(int code) {
this.code = code;
}
public int getCode() {
return code;
}
public void setCode(int code) {
this.code = code;
}
}
For example:
Manufacturers m = Manufacturers.Honda;
System.out.println(m.getCode()); // prints 10
m.setCode(100);
System.out.println(m.getCode()); // prints 100
Just be aware that you won't be able to reconstruct an Enum object from the code attribute, since that was defined by the programmer.

Related

Guava getIfPresent() Incorrect return

I am trying to use guava's getIfPresent() for an enum as below:
private enum LegalColumns
{
PRODUCERS_CUT("PRODUCER'S CUT", PMCColumnsEnum.NETWORK_CUT_1.getColumnName()),
PROPOSED_LOCKED_CUT("PROPOSED LOCKED CUT", PMCColumnsEnum.NETWORK_CUT_3.getColumnName()),
LOCK("LOCK", PMCColumnsEnum.LOCKED_DELIVERY.getColumnName()),
FINAL_MIX("FINAL MIX", PMCColumnsEnum.MIX_DATE.getColumnName());
private String column;
private String replacementColumn;
LegalColumns(String column, String replacementColumn) {
this.column = column;
this.replacementColumn = replacementColumn;
}
public static LegalColumns getIfPresent(String column) {
System.out.println(Enums.getIfPresent(LegalColumns.class, column.trim().toUpperCase()));
return Enums.getIfPresent(LegalColumns.class, column.toUpperCase()).orNull();
}
}
When I step through this however, it always prints out Optional.absent() despite the strings being exact matches. I followed, to my knowledge, the guava spec exactly. Any ideas what I am missing?
https://google.github.io/guava/releases/15.0/api/docs/com/google/common/base/Enums.html#getIfPresent(java.lang.Class,%20java.lang.String)
Returns an optional enum constant for the given type, using
Enum.valueOf(java.lang.Class, java.lang.String). If the constant
does not exist, Optional.absent() is returned. A common use case is
for parsing user input or falling back to a default enum constant. For
example, Enums.getIfPresent(Country.class,
countryInput).or(Country.DEFAULT);
https://docs.oracle.com/javase/6/docs/api/java/lang/Enum.html?is-external=true#valueOf(java.lang.Class,%20java.lang.String)
Returns the enum constant of the specified enum type with the
specified name. The name must match exactly an identifier used to
declare an enum constant in this type. (Extraneous whitespace
characters are not permitted.)
From your comment
I have gone with another approach, but for others, I passed in columns like "FINAL MIX".
"FINAL MIX" != "FINAL_MIX"
Guava uses the enum identifier, not the string you pass into the constructor.
So for the enum instance, FINAL_MIX("FINAL MIX", PMCColumnsEnum.MIX_DATE.getColumnName()); the enum identifier is "FINAL_MIX" not the string you pass in "FINAL MIX"
IN ADDITION! as you do not define a Locale on your string.toUpperCase, you are at risk of the turkey I bug.

Set custom variables from method

I have some String variables:
private String cur, last, avg, vol, shop;
I have method which accept String and gives me some result:
public void SomeMethod(String somestring)
{
//Here some action with `string`
System.out.print(result)
}
So i want to put result into one of String variables, but this variable must be named as value of somestring in my method. Some method which compare somestring with existent variables names. Is such a thing even possible?
You're talking about variable variable name. They're a native feature in PHP, but not in Java, however you can achieve similar functionality using a HashMap, or using Reflection. I'm going to show you the HashMap option, because frankly Reflection is the work of Satan.
Example
Now the way to implement this is like this:
public void someMethod(String name, String value)
{
values.put(name, value);
}
And you can retrieve them with
public void getValue(String name)
{
return values.get(name);
}
I won't write the code for you, because it's a simple transformation to get this to work in your use case.
A hint because I'm feeling nice
You can replace all of your String variables with a Map implementation. Then simply add the values to the Map, as and when the need arises.

Change from String to Object Name Java

I have 3 ints named A, B, and C. These are to be multiplied with the number 52. I have a string that contains the name of which int I want to mulitply (in example below my string type == A;.
I want to know if there is anyway to make the name of the String change into the name of the object/int that I wish to use.
What I have right now:
public class MultiplySomeNumbers{
int A = 100;
int B = 200;
int C = 300;
String type = "A";
final int multiplied = 52;
public int multiply(String type){
return multiplied* ____ //What goes here?
}
}
I DON'T want to do anything like this:
public int multiply(String type){
if(type.equalsIgnoreCase("A"){
return multiplied*A;
}else if(type.equalsIgnoreCase("B"){
...
Any help would be greatly appreciated!
No, that is not possible (maybe with Reflection, but it's still a no-go). Every single situation where you think you might need this does not need it.
There are several issues, but here are a few:
No intellisense for those generated variables
Very unclear code
Ambiguous naming (what if you create a new variable that happens to have the same name as a generated one?)
etc etc etc
You will have to go with your second option.
We might be able to provide a different solution, but the question is rather unclear as it is right now. Perhaps you could expand a little so we can help you better.
Although there may be a way to do this with reflection, it's probably a really bad idea. If you really can't just pass in the value, but want to specify a limited set of constants by which you can multiply, I'd recommend creating an enumerated type.
Taking your same example, but using an enum instead of trying to look up constants by name, would look something like this:
public class MultiplySomeNumbers{
public enum Type {
A(100),
B(200),
C(300);
private final int value;
private Type(int value) {
this.value = value;
}
public final int getValue() {
return value;
}
}
Type type = Type.A;
final int multiplied = 52;
public int multiply(Type type){
return multiplied * type.getValue();
}
}
While there is nothing wrong with using an enum for this solution, it may not be the most flexible solution. Enums are, by design, effectively immutable ... they are intended to have the sense of constants. If you wish to change the value of a variable by multiplying its value by 52, then this is not possible with enums.
What I think you really should do is use a HashMap. A Map is a key / value pair.
The key is the "variable's name"; a String quantity
The value is the "variable's current value"; an Integer quantity (not int!)
Your Map can be declared like this:
Map<String, Integer> myVariables = new HashMap<String, Integer>();
then to load your variables into the map, you simply call the Map's put() method:
myVariables.put("A", Integer.valueOf(100));
myVariables.put("B", Integer.valueOf(200));
myVariables.put("C", Integer.valueOf(300));
Retrieving the value of a variable is as simple as using the get() method with your variable name as the key:
int val = myVariables.get("A").intValue();
Notice that I have chosen to box and unbox the primitive int values myself rather than rely on autoboxing. This is just a personal choice. It does trade off conciseness, but I'd rather see what's actually happening.
In my opinion, using reflection to determine a class field to access dynamically at run time is wholly unsatisfactory and should be avoided ... most especially since using the Java Collections API enables a statically typed, type safe solution that can be checked at compile time.
You can't check for a variable's name. For more information look here, there are some good answers:
Java Reflection: How to get the name of a variable?
But maybe a HashMap can help you, where you store "A", "B", "C" as keys and the respective numbers as value.
edit: Okay, maybe with something like this http://docs.oracle.com/javase/6/docs/api/java/lang/reflect/Field.html it could be possible.

Checking Member Variable of Enum Without Iterating

I have an enum like that:
public enum Lang {
TR("tr"),
EN("en"),
SE("se");
private String langName;
private Lang(String langName) {
this.langName = langName;
}
}
at another class I want to check whether a langName exists or not. If I put a getter method I can iterate over langNames:
for (Lang langEnum : Lang.values()) {
langEnum.getLangName();
}
However my enum may be too long and I don't want to iterate over an array. I want to use a Map or Set. On the other hand I don't want to another variable within my enum.
How can I check whether my enum has a langName or not?
Well, if every enum constant represents a language (as the code seems to suggest), then I would use an EnumSet.
Set<Lang> langs = EnumSet.allOf(Lang.class);
And then I can check if a language is already there. Like
if(langs.contains(Lang.EN) {
//...
}
Not sure if this is the answer you were looking for. The contains method of EnumSet would not even iterate over the internal collection. The internal collection would be stored in an array and finding an element is calculated based on a hash. So, this in fact, should achieve what you requested in the question.
How about using valueOf?
Lang lang = null;
try {
lang = Lang.valueOf(enumName);
// enum exists
} catch (IllegalArgumentException e) {
// enum does not exist
}
Since your enum name is just the language name capitalized, you can just capitalize the language name and pass it into valueOf.

Map with two Key for a value?

I want to create a map that has two key :
map.put (key1,key2,value1);// Insert into map
map.get(key1,key2); // return value1
i have looking into multikeyMap but i don't know how i will do it
Sounds like you just want a key which is created from two values. You may well find that those two values should naturally be encapsulated into another type anyway - or you could create a Key2<K1, K2> type. (The naming here would allow for Key3, Key4 etc. I wouldn't encourage you to go too far though.)
For something in between, you could create a private static class within the class where this is really needed (if it's only an internal implementation detail). If it's not a natural encapsulation (e.g. it's something like "name and population", which doesn't make sense outside this specific scenario) then it would be good in terms of keeping meaningful property names, but without exposing it publicly.
In any of these scenarios, you'll end up with a new type with two final variables which are initialized in the constructor, and which contribute to both equals and hashCode. For example:
public final class Key2<K1, K2> {
private final K1 part1;
private final K2 part2;
public Key2(K1 part1, K2 part2) {
this.part1 = part1;
this.part2 = part2;
}
#Override public boolean equals(Object other) {
if (!(other instanceof Key2)) {
return false;
}
// Can't find out the type arguments, unfortunately
Key2 rawOther = (Key2) other;
// TODO: Handle nullity
return part1.equals(rawOther.part1) &&
part2.equals(rawOther.part2);
}
#Override public int hashCode() {
// TODO: Handle nullity
int hash = 23;
hash = hash * 31 + part1.hashCode();
hash = hash * 31 + part2.hashCode();
return hash;
}
// TODO: Consider overriding toString and providing accessors.
}
The more situation-specific types would be slightly simpler as they wouldn't be generic - in particular this would mean you wouldn't need to worry about the type arguments, and you could give the variables better names.
How about
class Key{
private final String key1;
private final String key2;
//accessors + hashcode + equals()
}
and
Map<Key, Value> map
You might consider using one of Guava's Table implementations. From the documentation:
A collection that associates an ordered pair of keys, called a row key
and a column key, with a single value. A table may be sparse, with
only a small fraction of row key / column key pairs possessing a
corresponding value.
If you can use outside libraries, Guava provides exactly this as Table<R, C, V>, referring to the two keys as "row" and "column" respectively. (Disclosure: I contribute to Guava.)
Why not map key a String and concatinate key1+key2
If you always want to access via key1 and key2 together you could just concatenate them with a separator together as key and use a normal map.
It's unfortunate that Java does not support tuples at language level, and therefore you have to go for ad hoc structures like the ones showed in some answers here. This leads to atrocious amount of boilerplate and code duplication.
Functional Java has a library support for tuples. The class that fits the bill here is P2. The name means "product with 2 elements". (Product is just an algebraic term for composite types.) The library supports tuples of up to 8 elements. The P{n} classes override all the necessary methods
There is a class named P that provides a static factory method p for constructing tuples.
Usage:
import fj.P2;
import fj.Ord;
import fj.data.TreeMap;
import static fj.Ord.*;
import static fj.P.*;
TreeMap<P2<Integer, String>, String> m =
TreeMap.<P2<Integer, String>, String>empty(p2Ord(intOrd, stringOrd)).
set(p(1, "2"), "onetwo").
set(p(5, "3"), "fivethree");

Categories

Resources