Can someone explain lambdas?
Is using Lambda expressions whenever possible in java good practice? - Software Engineering Stack Exchange
What’s the use of lambda expressions?
Are lambda expressions used much by professional coders ?
Videos
So I’m reading a book on Java, and it’s talking about lambdas. The syntax seems simple enough, but the author hasn’t described why you would use them over a regular function. They’re being used in the context of functions that don’t have bodies (abstracts, I think?), but I don’t understand why I would use those either.
There are a number of criteria that should make you consider not using a lambda:
- Size The larger a lambda gets, the more difficult it makes it to follow the logic surrounding it.
- Repetition It's better to create a named function for repeated logic, although it's okay to repeat very simple lambdas that are spread apart.
- Naming If you can think of a great semantic name, you should use that instead, as it adds a lot of clarity to your code. I'm not talking names like
priceIsOver100.x -> x.price > 100is just as clear as that name. I mean names likeisEligibleVoterthat replace a long list of conditions. - Nesting Nested lambdas are really, really hard to read.
Don't go overboard. Remember, software is easily changed. When in doubt, write it both ways and see which is easier to read.
I support Karl Bielefeldt's answer, but want to provide a brief addition.
- Debugging Some IDE's struggle with scope inside of a lambda, and struggle to display member variables inside the context of a lambda. While hopefully this situation will change down the line, it can be annoying to maintain someone else's code when it is littered with lambdas.
So what’s the main reason lambda expressions are used? So instead of developers creating the implementation for an abstract method, now we just send the implementation itself.
What’s the main point of this? It basically does the same thing? What’s the added benefit that I’m not really seeing here?
Just been studying up on them some as I am basically a hobbyist who just getting back into Java after about 10 or 12 years away from coding much. I appreciate the way lambda's allow coders to bypass constructors, initialization and calling methods by name , but on the other hand if you already have a good knowledge of the object classes and available methods , why not just do that ?
Syntax is:
arguments -> body
where arguments can be either
()a single variable if the type of that variable can be inferred from the context
a sequence of variables, with or without types (or since Java 11, with
var), in parentheses.
Examples:(x),(x, y),(int x, int y),(var x, var y)(Java 11+).
The following are invalid:(int x, y),(x, var y),(var x, int y)
and body can be either an expression or a {...} block with statements. The expression (other than a method or constructor call) is simply returned, i.e. () -> 2 is equivalent to () -> {return 2;}
In case of lambda expressions like () -> f() (the body is a method or constructor call expression):
if
f()returnsvoid, they are equivalent to() -> { f(); }otherwise, they are equivalent to either
() -> { f(); }or() -> { return f(); }). The compiler infers it from the calling context, but usually it will prefer the latter.
Therefore, if you have two methods: void handle(Supplier<T>) and void handle(Runnable), then:
handle(() -> { return f(); })andhandle(() -> x)will call the first one,handle(() -> { f(); }will call the second one, andhandle(() -> f()):if
f()returnsvoidor a type that is not convertible toT, then it will call the second oneif
f()returns a type that is convertible toT, then it will call the first one
The compiler tries to match the type of the lambda to the context. I don't know the exact rules, but the answer to:
What would happen if there were two SwingUtilities.invokeLater methods which differ only in parameter list?
is: it depends on what would be those parameter lists. If the other invokeLater had also exactly one parameter and that parameter would be of type that is also an interface with one method of type void*(), well, then it would complain that it cannot figure out which method you mean.
Why are they written as they are? Well, I think it's because syntax in C# and Scala is almost the same (they use => rather than ->).
The syntax is
(parameter_list_here) -> { stuff_to_do; }
The curly braces can be omitted if it's a single expression. The regular parentheses around the parameter list can be omitted if it's a single parameter.
The syntax only works for all functional interfaces. The @FunctionalInterface annotation tells the compiler that you intend to write such an interface and gives a compile error if you do not meet the requirement(s) - for example it must only have 1 overrideable method.
@FunctionalInterface
interface TestInterface {
void dostuff();
}
Runnable is also declared like that. Other interfaces are not, and they cannot be used with lambda functions.
Now that we've made a new functional interface with a method that takes no parameters, how about we test the question you had about "collision" in the signatures?
public class Main {
private void test(Runnable r) {
}
private void test(TestInterface ti) {
}
public static void main(String[] args) {
test(() -> { System.out.println("test");})
}
@FunctionalInterface
interface TestInterface {
void dostuff();
}
}
Result: compile error: ambigouous call to method test.
You see, the compiler/VM(if done runtime) finds the appropriate methods and their parameter list and sees if the parameter is a functional interface and if it is it creates an anonymous implementation of that interface. Technically (in byte code) it's different from an anonymous class, but otherwise identical (you won't see Main$1.class files).
Your example code (courtesy of Netbeans) can also be replaced with
SwingUtilities.invokeLater(MainAppJFrame::new);
Btw. :)