I have a HashMap as below:
public static HashMap submitService(HashMap inputMap) throws Exception
{
//code....
ArrayList<String> allIdsList = (ArrayList<String>) inputMap.get("Result_List");
// System.out.println("Result List: " + allIdsList); prints the arraylist (e.g. [2, 21, 6, 3]
for(int i=0;i<allIdsList.size();i++)
{
System.out.println(" values: " + (String)allIdsList.get(i));
}
}
the arraylist is printing in the console(I tried it only to see if the list is not empty). But for (String)allIdsList.get(i) inside the for loop following error message is coming
java.lang.Long cannot be cast to java.lang.String
Would really appreciate someone's help.
Make sure HashMap is of type HashMap<String,ArrayList<String>>
Replace: public static submitService(HashMap<'String,ArrayList<'String>> inputMap) throws Exception
Looking at the exception, its sure that the parameter passed does not have arraylist of string.Looks like it might be ArrayList<'Object>(with long value present in the list which eventually is casted in String) or Arraylist<'Long>.
Try this:
public static HashMap<String,ArrayList<String>> submitService(HashMap<String,ArrayList<String>> inputMap) throws Exception
{
//code....
ArrayList<String> allIdsList = inputMap.get("Result_List");
for(int i=0;i<allIdsList.size();i++)
{
System.out.println(" values: " + allIdsList.get(i));
}
}
Where is this inputMap coming from? By the looks of it, its values are not of type ArrayList<String> but something like ArrayList<Object> or even ArrayList<Long>. The problem seems to be somewhere outside your posted snippet.
Since you're working with raw types in this method, the compiler won't complain (although it should warn you about using raw types). However, the VM will throw a ClassCastException where the cast fails - that's what you're seeing.
Try strengthening your signature by only accepting HashMap<String, ArrayList<String>> as inputMap. That way, you can get rid of those awful casts, as you now get compile time type checks. In the best case, this will give the compiler enough information to point out where you're calling this method with an incorrectly typed inputMap. You should then be able to easily fix the error merely by following the compiler's instructions. If that doesn't work, you're probably using raw types in your calls as well and you'll need to dig down the stack trace to fix those.
Related
This question already has answers here:
java: (String[])List.toArray() gives ClassCastException
(5 answers)
Collection.toArray() java.lang.ClassCastException
(4 answers)
Casting Object array into String array throws ClassCastException [duplicate]
(2 answers)
why does List<String>.toArray() return Object[] and not String[]? how to work around this?
(5 answers)
List class's toArray in Java- Why can't I convert a list of "Integer" to an "Integer" array?
(3 answers)
Closed 2 years ago.
My IDE (IntelliJ) shows this when highlighting over 'toArray':
java.util.ArrayList
public Object[] toArray()
This returns an Object[]; which to my knowledge means that casting is necessary for most uses. I'm not however sure if it will work in this case (this method is part of a generic class with parameter <Type>):
private Type evaluate(int operator_index){
ArrayList<Type> this_args = new ArrayList<Type>();
for (int index : operator_inputtedBy.get(operator_index)) {
if(index >= 0) {
this_args.add(evaluate(index));
}else{
this_args.add(args[-1-index]);
}
}
return operators.get(operator_index).operation((Type[]) this_args.toArray());
}
In what conditions will this cast fail (if any)? And what are the alternatives that do not require casting?
It always fails.
I'm sure you're wondering why. Let's try to explain:
Unlike generics, which are entirely a figment of the compiler's imagination, an array does know its 'component' type. You can ask it:
String[] strings = new String[10];
Object[] o = strings; // compiles. This is itself problematic, see later.
System.out.println(o.getClass().getComponentType()); // prints 'java.lang.String'
o[0] = Integer.valueOf(0); // hmmmmmmmm!!!!!
String str0 = strings[0]; // ... but... wait.. that's an Integer, not a String!
Tossing the above in a java file, it....
compiles??
Yes, it does. It shouldn't have, really - the reason it compiles, even today, is that java started out allowing the above, and java does not like breaking backwards compatibility. This code used to compile, so it still does. But this is obviously not right - I have put an integer in a string array. And that's why when you run it, this does not work: You get an ArrayStoreException on the line where you put an integer into o[0].
Let's try this with generics. The same thing, just, genericsed:
List<String> strings = new ArrayList<String>();
List<Object> o = strings; // the evil occurs here
// hmmm, List doesn't appear to have a getComponentType()....
o.add(Integer.valueOf(0));
String str0 = strings.get(0);
Now, sanity has been restored: That second line, where the evil occurs? The compiler doesn't let you do that. As it shouldn't, because then you run into the problems that these snippets show. In computer science-ese, array assignment is covariant, whereas with generics it is invariant. In the real world, this stuff is invariant (hence why the first snippet blows up), so generics got it right, arrays got it wrong, but we can't fix it - java should be backwards compatible.
Now that you know this, the problems with toArray() become clear:
It is not possible for the toArray() method to know what component type the list is; therefore, if you have a List<String> and call toArray() on it, the toArray code cannot possibly obtain String from itself, unlike with arrays the component type is not stored. Generics are a figment of the compiler's imagination, it is nowhere in your class files, only in your source files. Thus, it doesn't know, so, it makes an array of objects (as in, the array that falls out of toArray() is technically an Object, calling its getComponentType will always print class java.lang.Object.
It is legal to assign a String[] to Object[], because the java lang spec defines arrays to be covariant. But real life isn't like that. Also, the lang spec also says that the reverse does not hold: You cannot cast an instance of Object[] to type String[]. This is why it will always fail - the toArray() method ALWAYS produces an Object[], which cannot be cast like that.
But let's say you could have hypothetically done that: If you then assign a non-string object to one of the array's slots, the ArrayStoreException does not happen, because the component type is incorrect.
And now you get a classcastexception later on when you read it back in.
Let's try it:
List<String> list = new ArrayList<String>();
list.add("Hello!");
String[] strings = (String[]) list.toArray(); // this fails...
Object[] o = strings;
o[0] = Integer.valueOf(5);
String str0 = strings[0]; // but otherwise you'd be in trouble here.
The solution
The fix is trivial:
NB: In java, we write 'operatorIndex', not 'operator_index'. When in rome, be like romans.
return operators.get(operatorIndex).operation(thisArgs.toArray(Type[]::new));
now you get no warnings, you don't need the cast, all is well. In this scenario at runtime the system does know how to make an array of Type (because you pass in a lambda that makes it). An alternative is this:
return operators.get(operatorIndex).operation(thisArgs.toArray(new Type[0]));
the provided array here (new Type[0]) is used only to get the component type, then the array is tossed in the garbage (it's a very short lived object, so it's free garbage, fortunately), and a new one is made, but now it WILL have the proper type; it'll be a Type[], and not an Object[].
TL;DR: Do not, ever, use collections' .toArray() method. It still exists, and will continue to exist... because of the backwards compatibility thing I talked about. That's the only reason.
Short answer: You cannot cast Object[] to String[] or MyClass[].
To solve your issue, you should use the version of toArray which accepts an array, for example: list.toArray(new String[0])
Here is a small working example which will show why it fails:
public static void main(String[] args) {
final ArrayList<String> list = new ArrayList<>();
list.add("abc");
list.add("def");
try {
final Integer[] intArray = (Integer[])list.toArray();
} catch (final Exception e) {
System.out.println(e.getMessage());
}
try {
final String[] stringArray = (String[])list.toArray();
} catch (final Exception e) {
System.out.println(e.getMessage());
}
try {
String[] stringArrayValid = list.toArray(new String[0]);
System.out.println("No Error!");
} catch (final Exception e) {
System.out.println(e.getMessage());
}
try {
Integer[] integerArrayInvalid = list.toArray(new Integer[0]);
} catch (final Exception e) {
System.out.println("Got Exception: " + e.getClass().getName());
}
}
Which prints:
[Ljava.lang.Object; cannot be cast to [Ljava.lang.Integer;
[Ljava.lang.Object; cannot be cast to [Ljava.lang.String;
No Error!
Got Exception: java.lang.ArrayStoreException
find-bug shows String can't cast to util.Map
When run through the application getting correct result.
siteList looks [{site_id=47, site_code=a}, {site_id=48, site_code=ABC}, {site_id=49, site_code=ABCD}, {site_id=54, site_code=ABCE}, {site_id=1, site_code=FXGL}]
public static List<SitesDto> transformSites(List<String> siteList) {
List<SitesDto> sitList = new ArrayList<>();
for (Object object : siteList) {
Map row = (Map) object;----->showing error
final SitesDto site = new SitesDto();
String code = (String) row.get(SITE_CODE);
Object id = row.get(SITE_ID);
site.setSiteId(((Number) id).longValue());
site.setSiteCode(code);
sitList.add(site);
}
return sitList;
}
find-bug shows String can't cast to util.Map
The java.util.Map interface represents a mapping between a key and a value.
Where as, siteList is a collection of Strings (they are not key and value pairs which Map is expecting), so is the error String can't cast to util.Map.
The List passed in parameter should be of List<Map<String,Object>>
Hope it helps.
You declare a method that accepts a List<String> argument. Since you say that the application runs without any apparent error, it would appear that the siteList argument is not actually a List<String> at all, but instead is a List<Map>. You should have got a findbugs warning somewhere else, probably in the method that calls transformSites, saying that you shouldn't be using raw types or that a List<Map> shouldn't be passed to a method that takes a List<String> argument. You should fix that first. You should also avoid using raw types: use List<whatever> instead of just List, and Map<String, Number> instead of just Map. Otherwise, you are making it easier to make errors.
Running my code results in the following error: java.lang.Integer cannot be cast to java.lang.String
This is what I have:
for(Map<String, Object> record: list) {
if(((String)record.get("level")).equals("1")) {
rootList.add(record);
}
}
I have tried converting that little snippet to an Int using toString but it just gives me a compiling error. I'm new to java (and I did not write this code either) so forgive me if it's a stupid mistake.
Your Maps holds values of type Object, meaning they can really hold anything as values (since everything extends Object); there's no guarantee that a given value will be a String. By your error, it would appear that one of the values in one of your maps is an Integer, which evidently cannot be cast to a String. The quick-fix is to use toString:
record.get("level").toString().equals("1")
But note that this will yield true for any object whose toString returns "1", not just strings. If you want to only check for equality with the string "1", then you can use "1".equals(...), since equals can take any object as an argument.
try
Object number = record.get("level");
if("1".equals(number)){
}
try one of this alternatives:
rootList.add(record + "");
or
rootList.add(new String(record));
Well, if the Map values are Integers, then toString() should work for converting them to strings:
for(Map<String, Object> record: list) {
if(record.get("level").toString().equals("1")) {
rootList.add(record);
}
}
I want to parse some Strings (they include some numbers) with same format but different number kind and set these number to their related array. for example having this string: " "positions":[[35.23,436.34],[23.5, 7.1]] I want to put these number into a float array named "this"! and for this string" "indices":[[23,4],[2,1]]" I want to put them into an integer array named "that"!
To do so, I've wrote a generic function with this declaration:
private <E extends Number> voidfunc(ArrayList<E> array, String JSON){
.
.
array.add((E) NumberFormat.getInstance().parse(JSON.substring(...)));
.
.
}
this works well and put numbers into array correctly but later, in somewhere in my app I get a "class cast exception. Can not cast Double to Float" trying to do this:
floatArray[i] = temp.get(i);
temp have defined as a float arraylist and have filled with above function.
can anybody tell me why it is so, and how can I solve that? I really appreciate that.
In your example, E is type parameter of generic method. This type is not known at run time, so cast to this type done with (E) is fake and compiler most probably reported warning at this line. JVM does not check type compatibility during this cast, so it is possible that value of incompatible type will get into the list. For example, value of Double type may be stored in List<Float>. Later, when you try to extract value form the list and cast it to Float, ClassCastException will occur.
You probably need to change your code like this:
private void func (ArrayList <? super Double> array, String JSON)
{
...
array.add (NumberFormat.getInstance ().parse (JSON.substring (...)));
...
}
ArrayList <Number> temp = new ArrayList ();
func (temp, json);
floatArray [i] = temp.get (i).floatValue ();
Try with:
floatArray[i] = ((Double) temp.get(i)).floatValue();
The method does not show any error but I am unable to use it in main method to display the list.
if (userinput.equalsIgnoreCase("push") )
{ calc.push(value);
calc.displaylist();
System.out.println(calc.getValues());
}
else if (userinput.equalsIgnoreCase("mult"))
{ calc.push(calc.mult());
calc.getValues(); }
how to use this method ... instead i used a methos called display list and that works but i need to know how to use my getValues method. both the methods are as below :
Double[] getValues()
{
Double[] array = new Double[values.size()];
return values.toArray(array);
}
void displaylist()
{
for(Double d : values)
System.out.println(d);
}
You can use a static method called toString(Object[]) in the java.util.Arrays class.
Well your displaylist() method contains a for-each loop that will iterate over the contents of a collection. The collection to iterate over is on the right side of the ':'. You've got a method that returns a collection - specifically, a Double[] - so you can call your getValues() method in place of the collection.
So, try this:
void displaylist()
{
for(Double d : getValues()) System.out.println(d);
}
I'm trying to understand the question - Let me restate it and see if I got it or not:
You have an object that has a Collection (probably a List) of values called values.
You have a method, getValues(), which returns an array containing all of the values in values.
You would like to print out all of the values in values.
You are required (homework?) to use the getValues() method when printing out values in values. (If you're not required to use getValues(), then I don't see what's wrong with the displaylist() method that you already wrote.)
You tried to just call System.out.println() on the array that you got from getValues(), but that just printed something awful like "[Ljava.lang.Double;#39172e08".
Did I get it?
Unfortunately, even with all that, I'm not sure what to suggest because I don't know what you want the printed out version to look like.
Should the values be separated by commas? If so, Ash's answer will do this for you.
Should each one be on its own line? If so, Shakedown's answer will do this for you.
Should the values just be separated by spaces? If so, then you can modify Shakedown's answer to use print(d + " ") instead of println(d).