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);
}
}
Related
I have the following function in java and I need to convert it to Kotlin.
#Override
public void afterTextChanged(Editable s) {
if (s != null && !"".equals(s.toString())) {
int position = (Integer) mHolder.numEdit.getTag();
// Saved to the data variable when the data changes
mData.get(position).put("list_item_inputvalue",
s.toString());
}
}
This is the equivalent Kotlin code that I've created:
override fun afterTextChanged(s: Editable?) {
if (s != null && "" != s.toString()) {
val position = mHolder.numEdit!!.tag as Int
// Saved to the data variable when the data changes
mData?.get(position).put("list_item_inputvalue", s.toString())
}
}
The compiler doesn't like the call to .put(). The variable mData in Java is:
private List<Map<String, String>> mData;
and Kotlin:
var mData: List<Map<String, String>>? = null
Why doesn't the compiler like the conversion of put in Kotlin?
UPDATE:
println(mData) = [{list_item_inputvalue=0}, {list_item_inputvalue=1},...]
println(mData?.get(position)) = {list_item_inputvalue=8}
Code in Java
Your problem centers around this statement in your question:
var mData: List<Map<String, String>>? = null
In Kotlin, the Map type is immutable, and so has no .put() method. That's the problem you're running up against. To fix it, just change this statement to:
var mData: List<MutableMap<String, String>>? = null
A second '?' is necessary after mData?.get(position) because that statement will return null if mData == null. That is, that statement returns a type of MutableMap<String, String>? even though the .put() by itself would return a type of MutableMap<String, String>.
To summarize...if you create a list of mutable maps, the compiler will then be happy with the statement:
mData?.get(position)?.put("list_item_inputvalue", s.toString())
Initially, it wasn't clear what exactly the question was, so let's start with the various syntax elements in here:
!!: the not-null assertion operator (!!) converts any value to a non-null type and throws an exception if the value is null. We can write b!!, and this will return a non-null value of b (e.g., a String in our example) or throw an NPE if b is null (quoted from kotlinlang)
[position]: Square brackets are translated to calls to get and set with appropriate numbers of arguments. (again, from kotlinlang) In other words:
that is simply "syntactic" sugar: you can treat a collection (probably a list) as an array. Meaning: instead of writing down get(index) to denote an element in a list, you can just go [index] as if that were an ordinary array.
Kotlin allows to use someMap[someKey] for its own maps. So, to answer the initial question, a further "conversion" could replace the call to put() via square brackets as well.
In that case, you have to be aware of the fact that Kotlin maps are immutable by default (so when using mapOf() you get a immutable map). Or, if you want to have a mutable Kotlin map "around" a Java map, you have to use mutableMapOf()!
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.
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.
HashMap<String, String> config = Feeds.config;
String num = config.get("NumOfFeeds");
System.out.println(num);
feedsAmount = ((Integer)num).intValue();
System.out.println(feedsAmount);
I've also tried Integer.parseInt(num) and Integer.decode(num) and Integer.valueof(bu)
Results as follows: 40
Exception in thread "main" java.lang.NumberFormatException: For input string:"40"
at java.lang.NumberFormatException.forInputString(NumberFormatException.java:48)
at java.lang.Integer.parseInt(Integer.java:458)
at java.lang.Integer.parseInt(Integer.java:499)
at fetch_RSS.<init>(fetch_RSS.java:40)
at testing.main(testing.java:27)
The problem was caused by different encoding from the txt file I'm reading from and the encoding in Elipse which is the macRoman by default.
The correct way of working is this:
String num = config.get("NumOfFeeds");
int feeds = Integer.parseInt(num);
This, only when you are sure that the String is representing a number the valid way.
-30 // correct
0 // correct
2000 // correct
"40" // invalid
40 // valid
2.000 // invalid
2.000.000 // invalid
20,0 // invalid
2,000,000 // invalid
Your exception got raised in Integer.java:458.
Looking into the source code of Integer I see that some characters of your String "40" returned a negative value (most probably -1) for Character.digit(s.charAt(i++), radix) where i is iterating over String's characters and radix is 10.
This should not happen normally. But it happens when the String is "4o" and not "40" like #Løkling's wild guess in the comments.
You should debug here to see what really happens.
Of course you can't cast from String to Integer. A String is not a Integer, and Integer is not a String.
You have to use int i = Integer.parseInt(..). It works if the string is a properly formatted integer.
For a cast to succeed in Java, the reference being cast must point to an object that is actually an instance of the type being cast to. A reference to String can't be cast to Integer because an object couldn't possibly be both things.
(This is somewhat unlike a cast in C, which is basically just saying, reinterpret the data stored here according to a different datatype. It would still be incorrect in C to use casting as a method to convert a string representing a number to a numeric value.)
Integer.parseInt is what you are looking for here. What problem are you having with it?
Remember : In java, we can only cast between objects if they are EXPLICITLY of the same type ! In other languages , like python, we can do the casting you requested here, because those languages allow "duck typing".
You must use Integer.parseInt("1234"), to create an Integer object from a String.
Alternatively you could create an Object wrapper to your data :
class MyObject
{
Object input;
public MyObject(Object input)
{
this.input=input;
}
public Integer getInt()
{
return Integer.parseInt(input.toString());
}
public String getString()
{
return input.toString();
}
}
This would be overkill for your simple problem, however :)
I would like to read in the string {"a": 1.0} as a generic Java Object while keeping the same string format. However, when I try, Jackson automatically changes the internal representation to {a = 1}. In other words, how can I get the following code to print {"a": 1.0} instead of {a = 1}? Note that, I have to read it in as an Object (due to other program constraints).
import org.codehaus.jackson.map.ObjectMapper;
public class Main {
public static void main(String[] args) {
try
{
ObjectMapper mapper = new ObjectMapper();
Object myObject = mapper.readValue("{\"a\": 1.0}", Object.class);
System.out.println(myObject.toString());
}
catch (Exception e)
{
e.printStackTrace();
System.err.println(e.getMessage());
}
}
}
The created object will be a map (like the other comments) and so its toString produces what you're seeing, {a = 1}. To get your code to print something closer to your input value, you need to use Jackson to write it back out with something like:
System.out.println(mapper.writeValueAsString(myObject));
That gives me what I believe you're looking for:
{"a":1.0}
In other words, Jackson has deserialized your input string into an arbitrary Java object. When you call toString on the object, its own toString is, of course, used. This can write the object however it pleases, including using the method from Object. To reproduce the input string, you have to use Jackson to serialize our object back out.
You need an existing class that matches the desired json structure. Object is not such class. You can still refer to it as Object, if that's needed:
Object myObject = mapper.readValue("{\"a\": 1.0}", SomeClass.class);
If you use a debugger, you will see that the type of the returned Object is LinkedHashMap. So what you see is the output of LinkedHashMap.toString(). There's no way for Jackson to change that, so you can either cast it to a Map and create the String yourself or ask for another return type that generates the JSON String for you:
if(myObject instanceof Map<?, ?>){
final Map<?, ?> map = (Map<?, ?>) myObject;
final StringBuilder sb = new StringBuilder("{");
boolean first = true;
for(final Entry<?, ?> entry : map.entrySet()){
if(first){
first = false;
} else{
sb.append(",");
}
sb.append("\n\t'")
.append(entry.getKey())
.append("':'")
.append(entry.getValue())
.append("'");
}
if(!first){
sb.append("\n");
}
sb.append("}");
System.out.println(sb.toString());
} else{
System.out.println(myObject);
}
Output:
{
'a':'1.0'
}
When Jackson is told to bind JSON into Object.class, it does just that; but since it has no a priori knowledge of what might be in that JSON (or what classes one might want to use), it has to use most basic Java types: Maps, Lists, Numbers, Booleans and Strings. So any JSON Object is represented by Map; JSON Array by List, and so on.
If you want a custom object, you must specify its type; or, when serializing, enable inclusion of explicit type information ("polymorphic type handling"). This will add either class name, or type name, and can be used to deserialize back to exact type.
To do this, either type itself (or one of its supertypes) must use #JsonTypeInfo annotation; or, if it is an Object property, #JsonTypeInfo for property (field or method).