Hi I have Map of String values.
I want to cast this value at runtime.
e.g.
Map map = new HashMap();
map.put("key1","101");
map.put("key2","45.40");
Now runtime I know key1 is integer and key2 is double How can I cast this.
I tried this:
("101").getClass().cast(Integer).
////////////////////////////////////////////// e.g. ...........
String integerClass = "java.lang.Integer"; String strNum = "5"; Now How will you convert this strNum value "5" to Integer using integerClass.
.....Without using new Integer(strNum) directly
Thanks.
You can't linguistically cast a String
(a reference type) to an int
or a double
(a primitive numeric type). You'd have to convert them. Thankfully, there are standard methods to do them for you:
int Integer.parseInt(String)
double Double.parseDouble(String)
NumberFormatException
-- this may be thrown by the parseXXX
T Class<T>.cast(Object)
does something entirely different. It has to do with generics, reflection, type-tokens, etc.
That said, I noticed that you used a raw Map
type. Since this looks like a new code, it should be said that you should NOT use raw types in new code. It's possible that you may never need to convert from String
to int
/double
in the first place (or at least do it BEFORE you put them into the map).
A Map<String,Number>
(or perhaps a Map<String,Double>
) would be better, because the map is "type-safe"; you know it maps String
to Number
, and the compiler would ensure that you're not doing anything to violate this type invariant.
Based on OP's comments, it looks like something like this was desired:
import java.util.*;
public class MapTranslate {
static Object interpret(String s) {
Scanner sc = new Scanner(s);
return
sc.hasNextInt() ? sc.nextInt() :
sc.hasNextLong() ? sc.nextLong() :
sc.hasNextDouble() ? sc.nextDouble() :
sc.hasNext() ? sc.next() :
s;
}
public static void main(String[] args) {
Map<String,String> map1 = new HashMap<String,String>();
map1.put("One", "1");
map1.put("PI", "3.141592653589793");
map1.put("10^12", "1000000000000");
map1.put("Infinity", "oo");
map1.put("Blank", " ");
Map<String,Object> map2 = new HashMap<String,Object>();
for (Map.Entry<String,String> entry : map1.entrySet()) {
map2.put(entry.getKey(), interpret(entry.getValue()));
}
for (Map.Entry<String,Object> entry: map2.entrySet()) {
System.out.format("%s->[%s] (%s)%n",
entry.getKey(),
entry.getValue(),
entry.getValue().getClass().getSimpleName()
);
}
}
}
This produces:
PI->[3.141592653589793] (Double)
Infinity->[oo] (String)
One->[1] (Integer)
10^12->[1000000000000] (Long)
Blank->[ ] (String)
This is not the most robust (e.g. it doesn't handle null
keys/values), but it may be a good starting point. Note that it uses java.util.Scanner
and its hasXXX
methods; this way you don't have to worry about any NumberFormatException
.
Without understanding the big picture, though, it's hard to comment whether something like this is even a good idea to begin with.
This seems to also be an aspect of the question; the following should be instructive:
import java.lang.reflect.*;
public class ValueOfString {
static <T> T valueOf(Class<T> klazz, String arg) {
Exception cause = null;
T ret = null;
try {
ret = klazz.cast(
klazz.getDeclaredMethod("valueOf", String.class)
.invoke(null, arg)
);
} catch (NoSuchMethodException e) {
cause = e;
} catch (IllegalAccessException e) {
cause = e;
} catch (InvocationTargetException e) {
cause = e;
}
if (cause == null) {
return ret;
} else {
throw new IllegalArgumentException(cause);
}
}
public static void main(String[] args) throws ClassNotFoundException {
Integer ii = valueOf(Integer.class, "42"); // no need to cast!
System.out.println(ii); // prints "42"
Object o = valueOf(Class.forName("java.lang.Double"), "3.14159");
System.out.println(o);
System.out.println(o instanceof Double); // prints "true"
}
}
The above snippet uses type tokens and reflections to invoke static valueOf(String)
method. The use of reflection may not be justifiable in this case, however, and it may simply be better to just explicitly check what the desired conversion is, e.g. "java.lang.Integer"
, and then invoke Integer.valueOf
accordingly.
I had a similar problem and solved it using the GenericValidator Helper Class from the Apache Commons Project to find out what Datatype I assume could be in the string and then parse it.
public Object parseString(String myString) {
if (GenericValidator.isLong(myString)) {
return Long.parseLong(myString);
} else if (GenericValidator.isDouble(myString)) {
return Double.parseDouble(myString);
} else if (GenericValidator.isDate(myString, Locale.GERMAN)) {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("DD.MM.YYYY");
return LocalDate.parse(myString, formatter);
} else {
return myString;
}
}
https://commons.apache.org/proper/commons-validator/
You need to parse the string into a double, like this:
double d = Double.parseDouble("45.40");
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With