New feature of JDK8 Lambda expression

1. Basic syntax of Lambda expression in java8:

(x,y) -> {}

On the left is a parenthesis, which contains the parameters of the abstract method to be implemented. If there are several parameters, write several parameter names. If there is no parameter, write empty parentheses, and there is no need to declare the parameter type;

In the middle is a jdk8 newly defined arrow symbol;

On the right is a curly bracket. The implementation content of the abstract method is written in the bracket. When there are parameters, the corresponding parameters in the bracket on the left can be used directly, which is the same as the method body of the normal method;

Usage: when implementing an interface with only one abstract method, it will match the method itself. Write the parameter name corresponding to the number of parameters on the left side of the arrow and the implementation code of the method on the right side of the arrow (when the code is implemented as a single line, remove the braces {})

Example:

@Test
public void test() {
    //Enter a number and compare the size with 100

    //Implementation method 1: anonymous inner class:
    Comparable<Integer> comparable1 = new Comparable<Integer>() {
        @Override
        public int compareTo(Integer o) {
            return Integer.compare(o, 100);
        }
    };
    comparable1.compareTo(2);

    //Implementation method 2 Lambda expression: when implementing a Comparable interface with only one abstract method, it will automatically match to the compareTo method, write the parameter name corresponding to the number of parameters on the left side of the arrow, and write the implementation code of the method on the right side of the arrow
    Comparable<Integer> comparable2 = (x) -> Integer.compare(x, 100);
    comparable2.compareTo(2);
}

2. Functional programming of Lambda expressions requires the support of functional interfaces (interfaces with and only one abstract method). In order to prevent adding interfaces manually when using Lambda expressions, Java8 has built-in four core functional interfaces:

/**
 * Java8 Built in four core functional interfaces
 *
 * Consumer<T> :Consumer interface
 *              void acept(T t);
 *
 * Supplier<T> :Supply type interface
 *              T get();
 *
 * Function<T,R> :Functional interface
 *              R apply(T t);
 *
 * Predicate<T> :Assertive interface
 *              boolean test(T t);
 */
public static void main(String[] args) {
    //Use examples of built-in functional interfaces

    //Consumer interface: enter a parameter and print it out
    Consumer<String> consumer = (x) -> System.out.println(x);
    //Print string
    consumer.accept("hehe");

    //Supply type interface Supplier, which returns the specified string
    Supplier<String> supplier = () -> "Hello world!";
    //Get string
    supplier.get();

    //Functional interface Function: enter a string and return the length of the string
    Function<String, Integer> function = (x) -> x.length();
    //Get string length
    function.apply("Hello world!");

    //Assert interface Predicate, enter a number to judge whether it is greater than 0
    Predicate<Integer> predicate = (x) -> x > 0;
    //Obtain judgment results
    predicate.test(10);
}

In addition to these four interfaces, there are other multi parameter sub interfaces, which can be found by yourself.

3. In some cases, the business part to be implemented has a method implementation, which can be directly referenced. At this time, the method reference in Lambda expression can be used:

/**

  • Method reference: if any method in Lambda body has been implemented, we can use "method reference"
  •          It can be understood that a method reference is lambda Another form of expression
    
  • There are three main syntax formats:
  • Object:: instance method name
  • Class:: static method name
  • Class:: instance method name
    */
    Note on method reference: the parameters and return values of the referenced method must be consistent with the parameters and return values of the abstract method to be implemented
//Reference the printout method of the out object as the concrete implementation of the accept method of the Consumer interface
Consumer<String> consumer1 = System.out::println;
consumer1.accept("hehe");

//Common ways of lambda expressions
BiPredicate<String, String> bp1 = (x, y) -> x.equals(y);
//Method reference: Class:: instance method (the passed in parameters of the method are two parameters, and the first parameter is used as the method calling object and the second parameter is used as the parameter of the called method)
BiPredicate<String, String> bp2 = String::equals;

4. Constructor reference: constructor reference can be made when instantiating a class through a functional interface

Note: the constructor referenced is the same as the number and type of method parameters in the functional interface

//Common ways of lambda expressions
Supplier<Passenger> supplier1 = () -> new Passenger();
//Constructor reference: refers to a parameterless constructor by type inference
Supplier<Passenger> supplier2 = Passenger::new;

//Common ways of lambda expressions
BiFunction<String, String, Passenger> function1 = (x, y) -> new Passenger(x, y);
//Constructor reference: refers to a constructor with two String parameters by type inference
BiFunction<String, String, Passenger> function2 = Passenger::new;

5. Array reference:

//Common ways of lambda expressions
Function<Integer, String[]> fun1 = (x) -> new String[x];
String[] strs1 = fun1.apply(10);
//Array reference
Function<Integer, String[]> fun2 = String[]::new;
String[] strs2 = fun2.apply(10);

6. Application of stream

Use steps of Stream:
1 create a Stream object
2 perform intermediate operations
3. Execute termination operation
1) How to create a Stream object:

/**
 * Stream Use of:
 * 1 Create Stream object
 * 2 Intermediate operation
 * 3 Terminate operation
 */
public static void main(String[] args) {
    //stream object acquisition method:
    String[] strings = {"1", "2", "3", "4"};

    //Method 1: get stream object from array
    Stream<String> stream1 = Arrays.stream(strings);

    //Method 2: get stream object from collection
    List<String> list = Arrays.asList(strings);
    Stream<String> stream2 = list.stream();

    //Method 3: the stream static method of gets the stream object
    Stream<String> stream3 = Stream.of(strings);

    //Method 4: create an infinite stream (the starting value of seed, the method of repeating execution for an infinite number of times)
    //Infinite flow 1: iteration
    Stream<Integer> stream4 = Stream.iterate(0, x -> x + 2);
    //Infinite stream 2: generation
    Stream<Double> stream5 = Stream.generate(() -> Math.random());
}

2) Common intermediate operation methods of Stream:

//Stream common method (chain method, executed from top to bottom, and the object processed by the next method is the result processed by the previous method)
Arrays.stream(new Integer[]{1, 63, 3, 7, 11, 54, 34})
//Filter, pass in a Predicate assertion interface implementation, the Stream will traverse internally, and the elements whose assertions return true will be reserved (elements with reserved values greater than 4 are filtered here)
.filter(x -> x > 4)
//Truncate the flow and only get the first n elements (here get the first 2 elements that meet the filter conditions)
.limit(5)
//Skip elements, skip the first n elements, and get the following elements. If there are less than n elements in the stream, an empty stream will be returned, which is complementary to limit (elements other than the first element are taken here)
.skip(1)
//Map, process the elements in the stream, such as converting types, obtaining attribute values, etc., and pass in a Function interface implementation (add 5 to all the elements in the stream here)
.map(x -> x + 5)
//Natural sorting (default sorting according to Comparable, here Integer sorting from small to large)
.sorted()
//Custom sorting (sort by Comparator, which is sorted by Integer from large to small)
.sorted((x, y) -> -Integer.compare(x, y))
//Terminate the operation, traverse the elements in the stream, and pass in a Consumer interface implementation (here, simply print and output the elements in the stream)
.forEach(System.out::println);

3) Common termination methods of Stream:

//Terminate operation
Integer[] integers = {1, 63, 3, 7, 11, 54, 34};
 List<Integer> list = Arrays.asList(integers);

 //Match all elements and pass in a Predicate assertion interface implementation. When all elements meet the conditions, it returns true, otherwise it returns false (judge whether all elements are greater than 0 here)
 boolean b1 = list.stream().allMatch(x -> x > 0);

 //Match elements and pass in a Predicate assertion interface implementation. When at least one element meets the conditions, it returns true, otherwise it returns false (judge whether all elements are greater than 0 here)
 boolean b2 = list.stream().anyMatch(x -> x > 0);

 //If there is no matching element, pass in a Predicate assertion interface implementation. If no element meets the conditions, return true, otherwise return false (judge whether all elements are greater than 0 here)
 boolean b3 = list.stream().noneMatch(x -> x > 0);

 //Match first element
 Optional<Integer> o4 = list.stream().findFirst();

 //Match any element
 Optional<Integer> o5 = list.stream().findAny();

 //Gets the number of elements in the stream
 long l6 = list.stream().count();

 //Gets the minimum value in the stream that satisfies the condition
 Optional<Integer> min = list.stream().min(Integer::compare);
 System.out.println("min:" + min.get());

 //Gets the maximum value in the stream that satisfies the condition
 Optional<Integer> max = list.stream().max(Integer::compare);
 System.out.println("max:" + max.get());

 //Reduction (take identity as the starting x, the first element as y, and then calculate the calculation result as x with the next element to obtain the calculation result)
 Integer reduce = list.stream().reduce(0, (x, y) -> x + y);
 //Reduction (the starting x is not set, so there may be null pointers, so the return type is Optional)
 Optional<Integer> reduce1 = list.stream().reduce(Integer::sum);

 //Collection (convert the Stream to other forms, accept a Collector interface implementation, and use it to summarize the elements in the Stream)
 List<Integer> collect = list.stream().collect(Collectors.toList());
 //Convert to hashset
 HashSet<Integer> collect1 = list.stream().collect(Collectors.toCollection(HashSet::new));
 //Take the average value
 Double collect2 = list.stream().collect(Collectors.averagingInt((x) -> x));
 System.out.println("avg:" + collect2);
 //Sum
 Double collect3 = list.stream().collect(Collectors.summingDouble(x -> x));
 System.out.println("sum:" + collect3);

Keywords: Java

Added by jahstarr on Sat, 01 Jan 2022 14:23:23 +0200