Saurabh Kumar Saurabh Kumar - 4 months ago 19
Java Question

Solve no final variable inside Java 8 Stream

Is there is a way to convert the following code to Java 8 Stream.

final List ret = new ArrayList(values.size());
double tmp = startPrice;
for (final Iterator it = values.iterator(); it.hasNext();) {
final DiscountValue discountValue = ((DiscountValue) it.next()).apply(quantity, tmp, digits, currencyIsoCode);
tmp -= discountValue.getAppliedValue();
ret.add(discountValue);
}


Java 8 streams complains about no final variable tmp ? Is there a way to solve such situations ?

Local variable tmp defined in an enclosing scope must be final or effectively final

enter image description here

Answer

First, change the code to use generics and an enhanced for loop. Assuming values is then a List<DiscountValue>, this is what you get:

List<DiscountValue> ret = new ArrayList<>(values.size());
double tmp = startPrice;
for (DiscountValue value : values) {
    DiscountValue discountValue = value.apply(quantity, tmp, digits, currencyIsoCode);
    tmp -= discountValue.getAppliedValue();
    ret.add(discountValue);
}

I'd suggest staying with that, and not convert it to streams, but if you insist, you can use a one-element array as a value-holder.

Note that ret and tmp doesn't have to be declared final, as long as they are effectively-final.

List<DiscountValue> ret = new ArrayList<>(values.size());
double[] tmp = { startPrice };
values.stream().forEachOrdered(v -> {
    DiscountValue discountValue = v.apply(quantity, tmp[0], digits, currencyIsoCode);
    tmp[0] -= discountValue.getAppliedValue();
    ret.add(discountValue);
});

As you can see, you haven't gained anything by using streams. The code is actually worse, so ... don't.

Comments