使用流有条件地填充地图 – Java 8
我正在尝试将此(简化)代码翻译为使用Java-8流:
Map files = new ConcurrentHashMap(); 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")));
但是上面给出了关于intelliJ上所有line->line+"..."
的“循环推理”消息。 什么是循环推理? 这个逻辑中有错误吗?
我在SO上注意到了一些类似的问题。 但是他们建议使用interface(Map)而不是它的实现。 但是这里的files
被声明为Map
。
更新:添加更多上下文, content
是一个包含目录名称的String。 files
是一个包含多个文件路径的映射。 需要进入files
映射的文件路径取决于content
目录名是否已填充。
另一种解决方法是为收集器引入中间变量:
Collector> collector = (content != null) ? (Collectors.toConcurrentMap(line->"notnull"+line, line->line+"notnull")) : (Collectors.toConcurrentMap(line->line+"null", line->line+"null")); Map files = reader.lines().parallel().collect(collector);
此解决方案(与@JanXMarek提供的解决方案不同)不分配中间数组,也不检查每个输入行的content
。
循环推理是类型推断过程中的情况,当确定内部子表达式的类型时,必须确定外部子表达式的类型,但是在不知道内部子表达式的类型的情况下无法确定。 Java-8中的类型推断可以推断出在Stream
收集Collector
的类型是Collector
。 通常,当子表达式类型(这里我们谈论的是toConcurrentMap(...)
子表达式)无法显式确定时,如果外部上下文是方法调用,强制转换或赋值,则可以使用外部上下文来减少它。 但是外部上下文是?:
运算符,它有自己的复杂类型推理规则,所以这变得太多了,你应该帮助类型推断系统在某处指定显式类型。
你可以这样做
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]));
首先,将行映射到存储在数组(或某种Pair对象)中的(键,值)对,然后在收集器中将其再次拆分为键和值。
只是一个侧面说明。 我怀疑.parallel()在这种情况下有任何好处。 如果您使用标准Java API来读取文件,则下面的迭代器仍将按顺序读取文件。 将要并行执行的唯一事情就是改变线条。 出于好奇,我只是在我的电脑上尝试过它,没有.parallel(),速度提高了10%。
如果处理比读取流的输入慢一个数量级,则并行化是有意义的,这不是这里的情况。
- 如何在intellij JShell控制台中导入自定义类
- IntelliJ是否支持任何类型的模板自动创建多个文件?
- IntelliJ – 无法启动 – “JAVA_HOME没有指向有效的JVM安装”
- 是否有任何方法可以让IntelliJ IDEA在Java项目中识别Dagger 2生成的类?
- 如何使用IntelliJ将外部库的源和javadoc添加到gradle中?
- 错误:未指定模块。 IntelliJ IDEA Ultimate
- 使用Gradle编译项目时,IntelliJ究竟在做什么?
- 如何让Apache POI和JAXB协同工作?
- 是否可以在Intellij Idea中更改junit4 test的默认类名模板?