preface

JDk6 and JDK7 are the most commonly used Java versions in production environments, although the percentage of JDK8 use is still small since its release in March 2014. Expect JDK10 to be out by the end of the month. JDk8 introduces many new features, such as interface defaults, method references, Lambda expressions, functional interfaces, Optional, streams, etc., that are not uncommon in other languages but are rarely used in Java today. Most of the time, we will hold a relatively conservative attitude towards new things (in fact, they are not new) : anyway, our company has not used it, learning is useless; Let others tread pit first, I come to the tree under the good shade; Learning something new again? I haven’t learned JDK7, and TMD want to learn JDk8, 9, 10? Tired out of love ah, the author has always maintained this mentality, but a curious heart prompted me to small forward so a small step……

Curiosity

Common code often involves some multi-threaded things, such as using the Future and Callable to do some things, code examples are as follows:

Write the picture description here

The IDE language level is set to JDK8 or higher. The IDE language level is set to JDK8 or higher. The IDE language level is set to JDK8 or higher. With the curiosity of a boy, I browsed the prompt information silently, and the details are as follows:

Write the picture description here

My inner restlessness led me to click “Replace with lambda” a little bit. The code quickly switches:

Write the picture description here

What an AMAZING thing! The code was immediately much cleaner, and the entire implementation of the Callable interface retained only the key “()->” lambda demo “. This happens not only with Callable, but also with Runnable and Comparator. What does JDK8 do to them? ! Let’s take a DEMO to remove the veil step by step from the original dream

Step by step

Sort a list of numeric strings. This list is very simple, as follows:

List<String> list = Arrays.asList("2", "3", "1", "4");Copy the code

This requirement is simple and takes less than a minute to implement:

Comparator<String> comparator = new Comparator<String>() { @Override public int compare(String o1, String o2) { return Integer.valueOf(o1) - Integer.valueOf(o2); }}; list.sort(comparator);Copy the code

Note that the JDK version used in this article is 8, so don’t be surprised to see the List’s sort() method, which is a new method implemented on the List interface using the default method: Default void sort(Comparator

list.sort(new Comparator<String>() {    @Override    public int compare(String o1, String o2) {        return Integer.valueOf(o1) - Integer.valueOf(o2);    }});Copy the code

If it’s JDK7, use the collections.sort () method and the implementation is pretty much done here, and then JDK8 is just getting started. We can further change the method to a Lambda expression:

list.sort((String o1, String o2) -> Integer.valueOf(o1) - Integer.valueOf(o2));Copy the code

All of a sudden, this is a line of code, but it looks a little more obscure than the original. As mentioned above, Callable, Runnable, and Comparator are all functional interfaces, and if you open the source code you will see that all three interfaces have the same annotation @funcationalInterface. If you are using a method that has a functional interface, you can use Lambda expressions. A FunctionalInterface is an interface that has only one abstract method. An interface labeled @functionalinterface will fail if it has no abstract method (the empty interface is the token interface, or the methods in the interface are the default methods) or more than one abstract method. Error: No target method found.) :

@FunctionalInterface  public interface FunctionError{}Copy the code

Multiple non-tprimary abstract methods found in interface FunctionError: (// Multiple non-tprimary abstract methods found in interface FunctionError)

@FunctionalInterfacepublic interface FunctionError{ public String method1(String o1, String o2); public String method2(Integer o1, Boolean o2); }Copy the code

Both methods are invalid, you can change one of the above methods to the default:

@FunctionalInterfacepublic interface FunctionCorrect{ public String method1(String o1, String o2); default public String method2(Integer o1, Boolean o2){ return "why not rabbitmq or kafka?" ; }; }Copy the code

That’s no problem.

A Lambda expression has three parts:

  • Parameter list. For the Comparable interface above, the argument list is “(String o1, String O2)” in “public int compare(String o1, String O2)”. For Callable/Runnable, its call/run method has no arguments, so it can be represented as a simple parenthesis ().

  • Arrow symbol: ->.

  • Body of a Lambda expression. ValueOf (o1) – integer.valueof (O2); . For the first example in this article, the Lambda subject is: “” Lambda demo.” The return type of the body of a Lambda expression = is the same as the return type of the methods in a functional interface. You can see that the basic syntax for Lambda is:

(Parameter list)-> expressionCopy the code

Or:

(Parameter list)-> {statement}Copy the code

Java can also infer the type of arguments in Lambda expressions, and the above code can further optimize the declaration to remove argument types:

list.sort((o1, o2) -> Integer.valueOf(o1) - Integer.valueOf(o2));Copy the code

For the above code, where Integer itself has a “Comparable” (implements the Comparable interface), the above code could be rewritten as:

list.sort((o1, o2) -> Integer.valueOf(o1).compareTo(Integer.valueOf(o2)));Copy the code

However, this code does not seem to be very readable, so we take it one step further and introduce a new concept called method references. Method references let you reuse existing method definitions and pass them around like lambdas, in some cases making them more readable. The above code can be further rewritten as:

list.sort(Comparator.comparing(Integer::valueOf));Copy the code

This code can see the value of type int when we sort the list of strings, without worrying about the somewhat arcane Lambda statement. What if one day the baby gets upset and instead of sorting by its converted int, sorts by its hashCode? It’s easy:

list.sort(Comparator.comparing(String::hashCode));Copy the code

If the baby does not open again, originally in ascending order, now in descending order what to do? Rewrite a Lambda expression like this:

list.sort((o1, o2) -> Integer.valueOf(o2).compareTo(Integer.valueOf(o1)));Copy the code

How about this:

list.sort(Comparator.comparing(Integer::valueOf).reversed()); //orlist.sort(Comparator.comparing(String::hashCode).reversed());Copy the code

Is it easy to understand and convenient? The basic idea behind method references is that if a Lambda simply represents a direct call to the method, it is better to call it by name rather than describing how to call it. In effect, a method reference lets you create a Lambda expression based on an existing method implementation, but explicitly specifying the method name makes the code more readable. When you use a method reference, place the target reference before the :: delimiter and the method name after it. Such as:

(String s) -> system.out.println (s) can be equivalent to system.out :printlnCopy the code

Why don’t you try the following code to see if it has the same effect?

public class FunctionDemo {    @FunctionalInterface    public interface FunctionQuote{        public void print(String arg);    }    public static void process(FunctionQuote functionQuote){        String str = "http://blog.csdn.net/u013256816";        functionQuote.print(str);    }    public static void main(String[] args) {        process((String s) -> System.out.println(s));        process(System.out::println);    }}Copy the code

If you feel that you have gained something after reading it, please click “like”, “follow” and add the official account “Ingenuity Zero” to check out more wonderful history!!