[英]working with streams problem of Local variable defined in an enclosing scope must be final
i have this algorithm that i want to change it with parallel streams so it makes less time for the calculation, but when i did it i got the error Local variable defined in an enclosing scope must be final for realiseValeur, nbValid and invalidite.So how can i work with parelle streams in this algorithm.我有这个算法,我想用并行流来改变它,这样计算的时间就更少了,但是当我这样做时,我得到了错误 Local variable defined in an enclosure scope must be final for realiseValeur, nbValid 和 invalidite。那么如何我可以在这个算法中使用 parelle 流吗? This is my algorithm in which i want to work with parallelstreams:
这是我想使用并行流的算法:
@Override
public Map<String, Double> getMapRealise(Date date, String code, Long pc) {
Map<String, Double> map = new HashMap<>();
List<Period> periodList = this.getListPeriod(date, code);
Double realiseValeur = 0.0;
Double invalidite = 0.0;
if (periodList != null) {
for (Period period : periodList) {
Double periode = this.getResolutionTraduiteEnHeures(period.getResolution().getV());
// Date dateDebutPrevisionnel =
// this.getDateDebutPrevisionnel(period.getTimeInterval().getV());
Double nbValid = 0.0;
for (Pt pt : period.getListPt()) {
realiseValeur += periode * pt.getQ().getV() / pcnTranche / NBR_HEURES_PAR_JOURS;
nbValid = nbValid + pt.getCq().getV();
}
if ((nbValid * periode) < NBR_HEURES_MINE_PAR_JOURS) {
invalidite++;
}
}
}
else {
LOGGER.warn( "n existe pas ");
}
map.put(REALISE_VALEUR, realiseValeur);
map.put(REALISE_INVALIDITE, invalidite);
return map;}
I tried this but i got the error Local variable defined in an enclosing scope must be final for realiseValeur, nbValid and invalidite:我试过这个,但我得到了错误 Local variable defined in an enclosure scope must be final for realiseValeur, nbValid and invalidite:
@Override
public Map<String, Double> getMapRealise(Date date, String code, Long pc) {
Map<String, Double> map = new HashMap<>();
List<Period> periodList = this.getListPeriod(date, code);
Double realiseValeur = 0.0;
Double invalidite = 0.0;
if (periodList != null) {
periodList.parallelStream().forEach(period -> {
Double periode = this.getResolutionTraduiteEnHeures(period.getResolution().getV());
// Date dateDebutPrevisionnel =
// this.getDateDebutPrevisionnel(period.getTimeInterval().getV());
Double nbValid = 0.0;
period.getListPt().parallelStream().forEach(pt -> {
realiseValeur += periode * pt.getQ().getV() / pcnTranche / NBR_HEURES_PAR_JOURS;
nbValid = nbValid + pt.getCq().getV();
});
if ((nbValid * periode) < NBR_HEURES_MINE_PAR_JOURS) {
invalidite++;
}
});
}
else {
LOGGER.warn("n existe pas ");
}
map.put(REALISE_VALEUR, realiseValeur);
map.put(REALISE_INVALIDITE, invalidite);
return map;
}
You need to return something from each iteration of the outer loop which has the incremental values for each of the iterations.您需要从外部循环的每次迭代中返回一些内容,其中包含每次迭代的增量值。
Stream<Map<String, Double>> fromParallel =
periodList.parallelStream()
.map(period -> {
double realiseValeurInc = 0.0;
double invaliditeInc = 0.0;
// Increment these variables instead of realiseValeur and invalidite
return Map.of(REALISE_VALEUR, realiseValeurInc, REALISE_INVALIDITE, invaliditeInc);
});
Now just merge all of these maps together:现在只需将所有这些地图合并在一起:
Map<String, Double> result =
fromParallel.reduce(
(a, b) -> Map.of(
REALISE_VALEUR, a.get(REALISE_VALEUR) + b.get(REALISE_VALEUR),
REALISE_INVALIDITE, a.get(REALISE_INVALIDITE) + b.get(REALISE_INVALIDITE)));
(You don't have to do this in two separate steps, that's merely to explain the process.) (您不必分两个单独的步骤执行此操作,这只是为了解释该过程。)
And you can use this as the return value (or copy this to a HashMap, if that's what you really need).您可以将其用作返回值(或将其复制到 HashMap,如果这是您真正需要的)。
Of course, this is wildly inefficient, because of all the allocation of both Double
and Map
.当然,这是非常低效的,因为
Double
和Map
的所有分配。 It will probably be slower than the existing loop-based code.它可能会比现有的基于循环的代码慢。 But it will at least give you the correct answer (eventually).
但它至少会给你正确的答案(最终)。
You can use AtomicInteger for this operation.您可以使用 AtomicInteger 进行此操作。 since you are using Double for your opeartions.
因为您使用 Double 进行操作。 create your own AtomicFloat and use it instead of Double and your problem will be solved:)
创建您自己的 AtomicFloat 并使用它而不是 Double ,您的问题将得到解决:)
import java.util.concurrent.atomic.AtomicInteger;
import static java.lang.Float.*;
class AtomicFloat extends Number {
private AtomicInteger bits;
public AtomicFloat() {
this(0f);
}
public AtomicFloat(float initialValue) {
bits = new AtomicInteger(floatToIntBits(initialValue));
}
public final boolean compareAndSet(float expect, float update) {
return bits.compareAndSet(floatToIntBits(expect),
floatToIntBits(update));
}
public final void set(float newValue) {
bits.set(floatToIntBits(newValue));
}
public final float get() {
return intBitsToFloat(bits.get());
}
public float floatValue() {
return get();
}
public final float getAndSet(float newValue) {
return intBitsToFloat(bits.getAndSet(floatToIntBits(newValue)));
}
public final boolean weakCompareAndSet(float expect, float update) {
return bits.weakCompareAndSet(floatToIntBits(expect),
floatToIntBits(update));
}
public double doubleValue() { return (double) floatValue(); }
public int intValue() { return (int) get(); }
public long longValue() { return (long) get(); }
}
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.