Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

java 8 local variable in stream.foreach [duplicate]

I would like to use local variables in lambda functions but I get error: Please see the 1. and 2. points in the code.

class Foo {
    int d = 0; // 1. It compiles, but ugly, 2. doesnt compile
    public void findMax(List<List<Route>> routeLists) {
        int d = 0; // 2.Error : Local variable dd defined in an enclosing scope must be final or effectively final
        routeLists.forEach(e-> {
            e.forEach(ee -> {
                d+=ee.getDistance();    
            });

        });
        ... doing some other operation with d
    }
}

How can I use them whitout setting them as global variables ?

like image 210
Csaba Prog Avatar asked Dec 24 '22 09:12

Csaba Prog


2 Answers

forEach is the wrong tool for the job.

int d =
    routeLists.stream()                // Makes a Stream<List<Route>>
        .flatMap(Collection::stream)   // Makes a Stream<Route>
        .mapToInt(Route::getDistance)  // Makes an IntStream of distances
        .sum();

Or just use nested for loops:

int d = 0;
for (List<Route> rs : routeLists) {
  for (Route r : rs) {
    d += r.getDistance();
  }
}
like image 179
Andy Turner Avatar answered Jan 09 '23 01:01

Andy Turner


You can't use an int as variable because it must be final to be used in a stream.

But You can create a class wrapping the int.

Then declare the variable holding this class as final.

Changing the content of the inner int variable.

public void findMax(List<List<Route>> routeLists) {
        final IntWrapper dWrapper = new IntWrapper();
        routeLists.forEach(e-> {
            e.forEach(ee -> {
                dWrapper.value += ee.getDistance();    
            });

        });

        int d = dWrapper.value;

        ... doing some other operation with d
    }

 public class IntWrapper {
    public int value;
 }
like image 33
Davide Lorenzo MARINO Avatar answered Jan 09 '23 01:01

Davide Lorenzo MARINO