3

I need to return a property of a certain object from which I need to access within a forEach loop. Basically I have a user object that that has a property of List<UserLocation> and inside the UserLocation object is a Location object with a property of location_id. If the store_id on the user object matches the store_id on the UserLocation object, that is the one I need to get the location_id from. However, the issue I am getting is that it says the variable used inside the lambda expression should be final or effectively final. See code below.

User user = getUser(request);
Integer locationId;

user.getUserLocations().forEach(ul -> {
    if (ul.getStoreId() == user.getStoreId()) {
        locationId= ul.getUserLocations().getLocationId();
    }
});

Any advice or solutions would be appreciated!

Jeffrey Chung
  • 19,319
  • 8
  • 34
  • 54
  • 2
    Possible duplicate of [variable used in lambda expression should be final or effectively final](http://stackoverflow.com/questions/34865383/variable-used-in-lambda-expression-should-be-final-or-effectively-final) – Andrii Abramov May 16 '17 at 18:52
  • Java doesn't have closures unfortunately, that's why you get compilation error. – randomUser56789 May 16 '17 at 19:07

2 Answers2

4

The error tells you exactly what the problem is: you cannot assign from inside a closure. You could work around this by making a mutable container, an array or a list, but a better approach is to use stream's findFirst method:

Optional<Integer> optLocationId = user.getUserLocations().stream()
    .filter(ul -> ul.getStoreId() == user.getStoreId())
    .findFirst();
if (optLocationId.isPresent()) {
    Integer locationId = optLocationId.get().getUserLocations().getLocationId();
}
Sergey Kalinichenko
  • 714,442
  • 84
  • 1,110
  • 1,523
1

This can be done better without forEach, assuming you only need to find one location :

Integer locationId = user.getUserLocations()
                         .stream()
                         .filter(ul -> ul.getStoreId() == user.getStoreId())
                         .findAny()
                         .map(ul -> ul.getLocation().getLocationId())
                         .orElse (0); // default value in case no match is found

P.S. I'm assuming ul.getUserLocations() is a typo, and should be ul.getLocation(), since you wrote that inside the UserLocation object is a Location object and getUserLocations() seems to be a method of the User class, not the UserLocation class.

Eran
  • 387,369
  • 54
  • 702
  • 768