将流和收集器与地图的ArrayList一起使用时,类型不兼容错误

时间:2018-09-21 19:35:04

标签: java arrays json arraylist java-stream

我有这样的代码:

    ArrayList<Map<String, String>> resultArray = resultList.stream() //
            .map(parser::parseJson) //
            .filter(ev -> ev.entrySet().containsAll(filter.entrySet())) //
            .collect(Collectors.toCollection(ArrayList::new));

调用方resultList是一个ArrayList,它是一个JSON数组。我想将每个元素解析为map,过滤map,并收集map的数组。

上一行代码没有编译错误。但是在运行时,它给出错误为:

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>>
>)

我尝试了多种不同的方式,例如Collectors.toList(),但是它不起作用。我仍然在寻找一种解决方案,可以解析每个String元素以进行映射并将它们全部收集为ArrayList。

更新:解析器来自com.json.parsers.JSONParser;

1 个答案:

答案 0 :(得分:1)

根据(几乎是神秘的)错误消息,问题出在您的parseJson实例的parser方法中,该方法返回了原始的Map,即没有映射的映射。 t指定其键和值的类型。

您需要该方法返回一个Map<String, String>,或者至少返回一个泛型,以便它可以返回所需的类型。


编辑:我从未听说过您的JSON解析器。谷歌快速搜索显示它几乎没有被使用,似乎它是一个已归档的项目。我强烈建议您使用更好的JSON库,例如Jackson,Gson或JSON.simple。

一种快速而又肮脏的解决方案是,如果您确定实际上已将字符串作为所有键的值,则将返回的映射强制转换为Map<String, String>(否则,您可能会感到恐惧) ClassCastException

为此,您应该将代码更改为:

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));

但是,再次提醒您,这不是很干净,您可能会在该演员表中引入更多错误。最好的解决方案是使用杰克逊:

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));

建议:最好将map操作中的整个try / catch块移到返回Map<String, String>的私有方法。