使用streams有条件地填充Map-java8

yiytaume  于 2021-07-13  发布在  Java
关注(0)|答案(3)|浏览(453)

我正在尝试将此(简化)代码转换为使用java-8流:

Map<String, String> files = new ConcurrentHashMap<String, String>();

while(((line = reader.readLine()) != null) {
      if(content != null)
        files.put("not null"+line, "not null"+line);
      else
        files.put("its null"+line, "its null"+line);
    }
reader.close();

以下是我尝试过的:

files = reader.lines().parallel().collect((content != null)?
                (Collectors.toConcurrentMap(line->"notnull"+line, line->line+"notnull")) :                                              
                (Collectors.toConcurrentMap(line->line+"null", line->line+"null")));

但是上面给出了一个“循环推理”的消息 line->line+"..." 关于intellij。什么是循环推理?这个逻辑有错误吗?
我注意到了一些类似的问题。但是他们建议使用接口(map)而不是它的实现。但是 files 这里被宣布为 Map .
更新:添加更多上下文, content 包含目录名称的字符串。 files 是一个包含多个文件路径的Map。哪些文件路径需要进入 files Map取决于 content 目录名是否已填充。

insrf1ej

insrf1ej1#

另一种解决方法是为收集器引入中间变量:

Collector<String, ?, ConcurrentMap<String, String>> collector = (content != null) ?
        (Collectors.toConcurrentMap(line->"notnull"+line, line->line+"notnull")) :
        (Collectors.toConcurrentMap(line->line+"null", line->line+"null"));
Map<String, String> files = reader.lines().parallel().collect(collector);

此解决方案(与@janxmarek提供的解决方案不同)不分配中间数组,也不检查 content 对于每个输入行。
循环推理是类型推理过程中确定内子表达式类型时,必须确定外子表达式的类型,但不知道内子表达式的类型就不能确定。java-8中的类型推断可以推断 Stream<String>.collect(Collectors.toConcurrentMap(line->line+"null", line->line+"null")) 收集器的类型为 Collector<String, ?, ConcurrentMap<String, String>> . 通常当子表达式类型 toConcurrentMap(...) 子表达式),如果外部上下文是方法调用、强制转换或赋值,则可以使用外部上下文对其进行缩减。然而,这里的外部环境是 ?: 运算符,它有自己复杂的类型推理规则,因此这变得太多,您应该帮助类型推理系统在某处指定显式类型。

s4n0splo

s4n0splo2#

你可以这样做

reader.lines().parallel()
    .map(line -> content == null ?
            new String[]{"notnull"+line, line+"notnull"} :
            new String[]{line+"null", line+"null"})
    .collect(Collectors.toConcurrentMap(pair -> pair[0], pair -> pair[1]));

首先,将该行Map到存储在数组(或某种pair对象)中的(键、值)对,然后在收集器中,将其再次拆分为键和值。

qojgxg4l

qojgxg4l3#

只是个旁注。在这种情况下,我怀疑.parallel()是否有用。如果您使用标准javaapi来读取文件,那么下面的迭代器仍将按顺序读取文件。唯一可以并行执行的是转换行。出于好奇,我刚在我的电脑上试过,没有.parallel()的话,速度快了10%。
如果处理比读取流的输入慢一个数量级,那么并行化是有意义的,这里不是这种情况。

相关问题