Java 8 Lambda问题在递增计数时有效最终

Lea*_*ner 0 java lambda final java-8

我想在下面的场景中使用Java 8 Lambda表达式,但我得到的是在封闭范围内定义的局部变量fooCount必须是final或者有效的final.我理解的错误消息说什么,但我需要计算在这里比例,从而需要增加fooCountbarCount再计算百分比.那么实现它的方法是什么:

        // key is a String with values like "FOO;SomethinElse" and value is Long
        final Map<String, Long> map = null;
    ....
    private int calculateFooPercentage() {
        long fooCount = 0L;
        long barCount = 0L;

        map.forEach((k, v) -> {
            if (k.contains("FOO")) {
                fooCount++;
            } else {
                barCount++;
            }
        });

        final int fooPercentage = 0;
        //Rest of the logic to calculate percentage
        ....
        return fooPercentage;
    }
Run Code Online (Sandbox Code Playgroud)

我有一个选择是在AtomicLong这里使用而不是long但我想避免它,所以稍后如果可能的话我想在这里使用并行流.

khe*_*ood 6

count流中有一种方法可以为您计数.

long fooCount = map.keySet().stream().filter(k -> k.contains("FOO")).count();
long barCount = map.size() - fooCount;
Run Code Online (Sandbox Code Playgroud)

如果要进行并行化,请更改.stream().parallelStream().

或者,如果您尝试手动增加变量,并使用流并行化,那么您可能希望使用类似于AtomicLong线程安全的东西.即使编译器允许,一个简单的变量也不是线程安全的.


Hol*_*ger 6

要获得数字,匹配和非匹配元素,您可以使用

Map<Boolean, Long> result = map.keySet().stream()
    .collect(Collectors.partitioningBy(k -> k.contains("FOO"), Collectors.counting()));
long fooCount = result.get(true);
long barCount = result.get(false);
Run Code Online (Sandbox Code Playgroud)

但由于您的源是a Map,它知道它的总大小,并且想要计算一个百分比,因此barCount不需要,这个特定的任务可以解决为

private int calculateFooPercentage() {
    return (int)(map.keySet().stream().filter(k -> k.contains("FOO")).count()
                 *100/map.size());
}
Run Code Online (Sandbox Code Playgroud)

两种变体都是线程安全的,即更改stream()parallelStream()将并行执行操作,但是,此操作不太可能从并行处理中受益.你需要庞大的钥匙串或地图来获得好处......