Reputation: 89
I have code like this:
ArrayList<Map<String, String>> resultArray = resultList.stream() //
.map(parser::parseJson) //
.filter(ev -> ev.entrySet().containsAll(filter.entrySet())) //
.collect(Collectors.toCollection(ArrayList::new));
The caller resultList
is an ArrayList, which is an array of JSON(s). I want to parse each element into map, filter the map, and collect the arrays of maps.
The code in the above line has no complier error. But at runtime it gives error as:
Error:(51, 25) java: incompatible types: cannot infer type-variable(s)
R,A,capture#1 of ?,T,C,E (argument mismatch;
java.util.stream.Collector<java.util.Map<java.lang.String,java.lang.String>,capture#2 of
?,java.util.ArrayList<java.util.Map<java.lang.String,java.lang.String>>
> cannot be converted to java.util.stream.Collector<? super
java.util.Map,capture#2 of
?,java.util.ArrayList<java.util.Map<java.lang.String,java.lang.String>>
>)
I've tried many different ways like Collectors.toList()
but it doesn't work. I'm still after a clean solution for parsing each String element to map and collecting all of them as an ArrayList.
Update: the parser is from com.json.parsers.JSONParser;
Upvotes: 2
Views: 4307
Reputation: 34450
According to the (almost cryptic) error message, the problem is in the parseJson
method of your parser
instance, which is returning a raw Map
, i.e. a map that doesn't specify the types of its keys and values.
You need that method to return a Map<String, String>
, or at least, to be generic, so that it can return the required type.
EDIT: I've never heard of your JSON parser. A quick google search showed that it is barely used and it seems like it's an archived project. I highly recommend you to move to a better JSON library, such as Jackson, Gson or maybe JSON.simple.
A quick and dirty solution with what you already have would be to cast the returned map to Map<String, String>
, if you're sure that you actually have strings as values for all your keys (otherwise you might face the dreaded ClassCastException
).
To accomplish this, you should change your code to:
List<Map<String, String>> resultArray = resultList.stream()
.map(json -> (Map<String, String>) parser.parseJson(json))
.filter(ev -> ev.entrySet().containsAll(filter.entrySet()))
.collect(Collectors.toCollection(ArrayList::new));
But, again, bear in mind that this is not very clean and that you might be introducing more bugs with that cast. Best solution would be to use i.e. Jackson:
ObjectMapper mapper = new ObjectMapper(); // Jackson JSON lib entry-point
List<Map<String, String>> resultArray = resultList.stream()
.map(json -> {
try {
return mapper.readValue(json, new TypeReference<Map<Striong, String>>() {});
} catch (IOException e) {
throw new UncheckedIOExpcetion(e);
}
})
.filter(ev -> ev.entrySet().containsAll(filter.entrySet()))
.collect(Collectors.toCollection(ArrayList::new));
Recommendation: you'd better move the whole try/catch block inside the map
operation to a private method that returns Map<String, String>
.
Upvotes: 3