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.