Populate a map conditionally using streams - Java 8

我与影子孤独终老i 提交于 2019-12-04 10:11:59

Another way to fix this is to introduce the intermediate variable for collector:

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

This solution (unlike one presented by @JanXMarek) does not allocate intermediate arrays and does not check the content for every input line.

The cyclic inference is the situation in the type inference procedure when to determine the type of inner subexpression, the type of outer subexpression must be determined, but it cannot be determined without knowing the type of inner subexpression. Type inference in Java-8 can infer that in case of Stream<String>.collect(Collectors.toConcurrentMap(line->line+"null", line->line+"null")) the type of Collector is Collector<String, ?, ConcurrentMap<String, String>>. Normally when subexpression type (here we're speaking about toConcurrentMap(...) subexpression) cannot be explicitly determined, it can be reduced using the outer context if the outer context is method invocation, cast or assignment. Here however the outer context is ?: operator which has its own complex type inference rules, so this becomes too much and you should help the type inference system specifying the explicit type somewhere.

You can do it like this

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

First, you map the line to a (key,value) pair stored in an array (or in some kind of a Pair object), and then, in the collector, you split it again into a key and a value.

Just a side-note. I doubt that .parallel() is of any good in this context. If you are using the standard Java API for reading files, the iterator underneath will still read the file sequentially. The only thing that will be executed in parallel will be transforming the lines. I just tried it on my PC, out of my curiosity, and it was about 10% faster without .parallel().

Parallelisation makes sense if the processing is an order of magnitude slower than reading the input of the stream, which is not the case here.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!