Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

like image 238
Saurabh Kumar Avatar asked Apr 26 '26 09:04

Saurabh Kumar


1 Answers

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.

like image 69
Andreas Avatar answered Apr 29 '26 01:04

Andreas



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!