preface
To prepare for the job interview, today begins the review of Java basics. I hope that students with poor foundation can master lambda expressions after reading this article, while students with good foundation can review it. I hope that after reading this article, you can have a bit of green memory.
What is a lambda expression
Java8 is our most widely used stable version of Java, and Lambda is the most notable new feature. Lambda is a closure that allows functions to be used as arguments, an idea for function-oriented programming that makes code look cleaner. Did you hear it all in a daze? Let me give you an example.
In the case of rotting teeth, before lambda, we wrote:
// Inner class
public class InnerClassMain {
public static void main(String[] args) {
// Anonymous inner class
new Thread(new Runnable() {
@Override
public void run(a) {
System.out.println("Inner class writing"); } }).start(); }}Copy the code
With lambda, we write lambda:
/ / lambda method
public class LambdaMain {
public static void main(String[] args) {
/ / lambda method
new Thread(() -> System.out.println("The lambda method")).start(); }}Copy the code
It should be noted that there are two ways to implement threads: one is to inherit the Thread class and the other is to implement the Runnable interface. This is the latter, which is a functional interface.
1.1 Functional interface
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run(a);
}
Copy the code
Runnable is a ** functional interface. ** this class of interfaces is characterized by the @functionalinterface annotation (which is used for compile-level error checking, so that the compiler will report an error when you write an interface that does not conform to the FunctionalInterface definition) and one and only abstract method. Such interfaces can use lambda expressions in the native JDk.
The above concept refers to using functions as arguments. In the lambda example above, the Thread argument is a Runnable interface, and lambda implements this interface and uses it as an argument. So the above () -> system.out.println (“lambda notation “) is an argument to an entire lambda expression (distinguish it from the method argument, which is covered later). A **lambda expression is an instance object that creates a functional interface for a class. * * such as:
Runnable runnable = () -> System.out.println("The lambda method");
Copy the code
Why are lambda expressions needed
Now that you know what a lambda expression is, why use it? Note that when we create threads using lambda, we don’t care about interface names, method names, and parameter names. We just focus on the type of arguments, the number of arguments, the return value. So the reason is to simplify code and improve readability.
How to use lambda expressions
3.1 lambda syntax
// The format follows: (interface argument)-> expression (concrete implementation method)
(paramters) -> expression 或 (parameters) ->{ expressions; }
Copy the code
For specific explanation, see the figure above. In addition, lambda syntax notes:
- Optional type declaration: Method parameters do not need to be declared as parameter types, and the compiler can uniformly identify parameter values.
- Optional parameter parentheses: You do not need to define parentheses for one parameter, but you need to define parentheses for no or multiple parameters.
- Optional curly braces: If the concrete implementation method has only one statement, the use of curly braces {} is unnecessary.
- Optional return keyword: If the implementation method has only one expression, the compiler automatically returns the value. If there are multiple expressions, the brackets need to specify that the expression returns a value.
Example:
public class Example {
// Define a functional interface. Only one abstract interface is allowed, otherwise an error will be reported
// If you want to detect an error at compile time, annotate @functionalInterface
public interface Hello {
String hi(a);
}
public interface Hello2 {
String hei(String hello);
}
public interface Hello3 {
String greet(String hello, String name);
}
public static void main(String[] args) {
// The input parameter is empty
Hello no_param = () -> "hi, no param";
Hello no_param2 = () -> {
return "hi, no param";
};
System.out.println(no_param.hi());
System.out.println(no_param2.hi());
// A single argument, a return statement, can omit the braces and return
Hello2 param = name -> name;
Hello2 param2 = name -> {
return name;
};
/ / print
System.out.println(param.hei("Hei, a good loser."));
System.out.println(param2.hei("Hei, a good loser."));
// Multiple parameters
Hello3 multiple = (String hello, String name) -> hello + "" + name;
// a return statement that can omit braces and return
Hello3 multiple2 = (hello, name) -> hello + name;
// Multiple processing statements, requiring braces and return
Hello3 multiple3 = (hello, name) -> {
System.out.println("Go inside.");
return hello + name;
};
/ / print
System.out.println(multiple.greet("hello,"."Best wishes for 2020."));
System.out.println(multiple2.greet("hello,"."Best wishes for 2020."));
System.out.println(multiple3.greet("hello,"."Best wishes for 2020.")); }}Copy the code
3.3 Method Reference
Look at a simple method reference example:
Consumer<String> sc = System.out::println;
sc.accept("A good loser.");
/ / equivalent
Consumer<String> sc2 = (x) -> System.out.println(x);
sc2.accept("A good loser.");
Copy the code
Consumer functional interface
@FunctionalInterface
public interface Consumer<T> {
void accept(T t);
}
Copy the code
You might be a little confused, but why would you write that? Consumer is a functional interface with the abstract method void Accept (T T) and arguments T. So now we have a requirement, and I want to take advantage of the abstract method of this interface, and do console printing. Normally, we would need to implement this interface and its abstract methods to implement this requirement:
public class ConsumerImpl implements Consumer<String> {
@Override
public void accept(String s) { System.out.println(s); }}Copy the code
After implementation, the abstract method becomes concrete. The function is console printing, which means that the abstract method can just be implemented with the actual method: System.out.println(s), so we can use method references.
Conclusion: Method references are used when abstract method implementations of functional interfaces happen to be implemented by calling an actual method.
Three forms of method references:
// Use the abstract method parameters as the actual method parametersObject: : instance methods objectName: : instanceMethod// Use the abstract method parameters as the actual method parametersClass ::staticMethod ClassName::staticMethod// take the first parameter of the method argument as the caller of the method, and the other parameters as the method argumentsClass: : instance methods ClassName: : instanceMethodCopy the code
Customize a method class:
public class Method {
// Static method
public static void StaticMethod(String name) {
System.out.println(name);
}
// Instance method
public void InstanceMethod(String name) {
System.out.println(name);
}
// no argument constructor
public Method(a) {}// There are arguments
public Method(String methodName) { System.out.println(methodName); }}Copy the code
Test cases:
public class MethodExample {
public static void main(String[] args) {
Static method references -- called by class name
Consumer<String> consumerStatic = Method::StaticMethod;
consumerStatic.accept("Static method");
/ / equivalent to the
Consumer<String> consumerStatic2 = (x) -> Method.StaticMethod(x);
consumerStatic2.accept("Static method");
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
// Non-static method references -- called by instance
Method method = new Method();
Consumer<String> consumerInstance = method::InstanceMethod;
consumerInstance.accept("Object instance methods");
/ / equivalent to the
Consumer<String> consumerInstance2 = (x) -> method.InstanceMethod(x);
consumerInstance2.accept("Object instance methods");
System.out.println("-- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -");
/ / the ClassName: : instanceMethod class instance methods: the expression of the first parameter as a instanceMethod caller, other parameters as the parameters of the method
BiPredicate<String, String> sbp = String::equals;
System.out.println("Instance method of class" + sbp.test("a"."A"));
/ / equivalent
BiPredicate<String, String> sbp2 = (x, y) -> x.equals(y);
System.out.println("Instance method of class" + sbp2.test("a"."A")); }}Copy the code
Output result:
Static methods static method -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - object instance methods of the object instance methods -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- - class instance methodsfalseClass instance methodfalse
Copy the code
3.4 Constructor references
public class ConstructMethodExample {
public static void main(String [] args) {
// Constructor method references -- no arguments (method references can be used)
Supplier<Method> supplier = Method::new;
System.out.println(supplier.get());
/ / equivalent to the
Supplier<Method> supplier2 = () -> new Method();
System.out.println(supplier2.get());
// Constructor method references -- with parameters
Function<String, Method> uf = name -> new Method(name);
Method method = uf.apply("A good loser."); System.out.println(method.toString()); }}Copy the code
- Reference: www.cnblogs.com/kingsonfu/p…
3.5 Variable scope
Lambda expressions can only refer to outer local variables that mark final, which means that local variables defined outside the domain cannot be modified inside the lambda, otherwise a compilation error will occur.
public class VariableScopeTest {
// Define an interface
public interface Converter<T1.T2> {
void convert(int i);
}
public static void main(String [] args) {
// It is defined as final and cannot be changed
final int num = 1;
Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num));
// The output is 3
s.convert(2); }}Copy the code
The variable is not declared final, so you can modify the external variable:
int num = 1; Converter<Integer, String> s = (param) -> System.out.println(String.valueOf(param + num)); s.convert(2);
Copy the code
In addition, it is not allowed to declare a parameter or local variable with the same name as a local variable in a Lambda expression
String first = "";
// The same name as the first variable, the compilation error
Comparator<String> comparator = (first, second) -> Integer.compare(first.length(), second.length());
Copy the code
Ten examples of lambda expressions
- Example: blog.csdn.net/qq_37176126…
Github source address: github.com/turoDog/rev…
The last
If you see this and like this article, please “forward” or click “Watching”, ok? I wish you all a fortune in 2020. Wechat search “an excellent waste person”, welcome to follow.
Reply “1024” to send you a complete set of Java, python, c++, go, front-end, Linux, algorithms, big data, artificial intelligence, applets and English tutorials.
Reply to “ebook” and get you 50+ Java ebooks.