Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Java: Assign a variable within lambda

I cannot do this in Java:

Optional<String> optStr = Optional.of("foo");
String result;
optStr.ifPresent(s -> result = s);

The doc says that the variables used in lambdas must be effectively final. Then how to extract and store something from a lambda into a variable nicely?

Actually the real use case is more complex.
I want to apply several regular expressions to a string one after another with matcher.replaceAll. I'm doing this in a forEach lambda and wanted to store intermediate results somewhere.

like image 946
George Avatar asked Nov 04 '15 09:11

George


People also ask

How do you declare a variable in lambda expression in Java?

A lambda expression can't define any new scope as an anonymous inner class does, so we can't declare a local variable with the same which is already declared in the enclosing scope of a lambda expression. Inside lambda expression, we can't assign any value to some local variable declared outside the lambda expression.

Can a lambda function be assigned to a variable?

Creating a Lambda Function The lambda operator cannot have any statements and it returns a function object that we can assign to any variable.

Can we use Non final local variables inside a lambda expression?

A lambda expression can use a local variable in outer scopes only if they are effectively final.

Can functional interface have variables?

The interface has only public variables and methods by default. It is not mandatory to associate non-access modifiers with variables of the class. Interfaces can have variables that are either static or final. We can instantiate and create objects from a class.


1 Answers

The answer is simple: you can't (directly) do that.

A very ugly hack would be to mutate an external object instead of assigning to a variable:

Optional<String> optStr = Optional.of("foo");
StringBuilder sb = new StringBuilder();
optStr.ifPresent(s -> sb.append(s));
String result = sb.toString();

This works because sb is effectively final here

But I want to emphasize the point that this is probably not what you really want to do.

  • If you want to have a default value, use optStr.orElse or optStr.orElseGet instead.
  • If you want to map the result only if it is present, use optStr.map

Since you did not provide your whole use-case, these are just guesses but the key point is that I really do not recommend the above snippet of code: it goes against the concept of functional programming (by mutating an object).

like image 151
Tunaki Avatar answered Sep 20 '22 19:09

Tunaki