Lambda expressions

Lambda is an anonymous function, and we can think of a Lambda expression as a piece of code that can be passed (passing code like data). It can be used to write more concise, more flexible code, as a more compact code generation style, so that the Java language expression ability has been improved.

Lambda expressions are a new syntax element and operator introduced in the Java8 language. The “->” operator is called the Lambda operator or arrow operator, which divides Lambda into two parts:

  • Left: specifiedLambdaA list of arguments required by the expression
  • Right: SpecifiedLambdaThe body is the implementation logic of the abstract method, i.eLambdaThe function to be performed by the expression.
import org.junit.Test;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.function.Consumer;

/** * pare(o1,o2) -> integer.pare (o1, O2); * 2. Format: * -> :lambda operator or arrow operator * -> Left :lambda parameter list (which is the abstract method parameter list in the interface) * -> Right: * <p> * 3. Use of lambda expressions: (divided into 6 cases) * <p> * Summary: * -> Left: the type of lambda parameter list can be omitted (type inference); If the lambda parameter list has only one argument, one pair of () can also be omitted * -> to the right: the lambda body should be wrapped with a pair of {}; If the lambda body has only one execution statement (possibly a return statement), omit this pair of {} and the return keyword * <p> * 4. The essence of a lambda expression: as an instance of a functional interface * <p> * 5. An interface that declares only one abstract method is called a functional interface. We can use it on one interface@FunctionalInterface Annotation, * To check if it is a functional interface. * <p> * 6. So everything previously represented by anonymous implementation classes can now be written as Lambda expressions. * /
public class LambdaTest1 {
    // Syntax format 1: no parameter, no return value
    @Test
    public void test1() {
        Runnable r1 = new Runnable() {
            @Override
            public void run() {
                System.out.println("I love Tiananmen Square in Beijing"); }}; r1.run(); System.out.println("* * * * * * * * * * * * * * * * * * * * * * *");

        Runnable r2 = () -> {
            System.out.println("I love the Forbidden City in Beijing");
        };

        r2.run();
    }

    Lambda takes one argument, but returns no value.
    @Test
    public void test2() {

        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s){ System.out.println(s); }}; con.accept("What's the difference between a lie and an oath?");

        System.out.println("* * * * * * * * * * * * * * * * * * *");

        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("One is listening to people seriously, and the other is talking to people seriously.");

    }

    // Data types can be omitted because they can be inferred by the compiler, called "type inference"
    @Test
    public void test3() {

        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("One is listening to people seriously, and the other is talking to people seriously.");

        System.out.println("* * * * * * * * * * * * * * * * * * *");

        Consumer<String> con2 = (s) -> {
            System.out.println(s);
        };
        con2.accept("One is listening to people seriously, and the other is talking to people seriously.");

    }

    @Test
    public void test4() {

        ArrayList<String> list = new ArrayList<>();// Type inference

        int[] arr = {1.2.3};// Type inference

    }

    If Lambda requires only one argument, the parentheses of the argument can be omitted
    @Test
    public void test5() {
        Consumer<String> con1 = (s) -> {
            System.out.println(s);
        };
        con1.accept("One is listening to people seriously, and the other is talking to people seriously.");

        System.out.println("* * * * * * * * * * * * * * * * * * *");

        Consumer<String> con2 = s -> {
            System.out.println(s);
        };
        con2.accept("One is listening to people seriously, and the other is talking to people seriously.");


    }

    Lambda takes two or more arguments, multiple execution statements, and can have a return value
    @Test
    public void test6() {

        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                returno1.compareTo(o2); }}; System.out.println(com1.compare(12.21));

        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * *");
        Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };

        System.out.println(com2.compare(12.6));


    }

    // If the Lambda body has only one statement, the return and braces, if present, can be omitted
    @Test
    public void test7() {

        Comparator<Integer> com1 = (o1, o2) -> {
            return o1.compareTo(o2);
        };

        System.out.println(com1.compare(12.6));

        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * *");

        Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);

        System.out.println(com2.compare(12.21));

    }

    @Test
    public void test8() {
        Consumer<String> con1 = s -> {
            System.out.println(s);
        };
        con1.accept("One is listening to people seriously, and the other is talking to people seriously.");

        System.out.println("* * * * * * * * * * * * * * * * * * * * * * * * * * * * *");

        Consumer<String> con2 = s -> System.out.println(s);

        con2.accept("One is listening to people seriously, and the other is talking to people seriously."); }}Copy the code

Built-in four function interfaces

  • Consumer interface: Consumer< T> void accept(T T) abstract method with arguments, no return value;
/** * consumer interface */
public class ConsumerInterface {
    public static void main(String[] args) {
        Consumer<String> stringConsumer = new Consumer<String>() {
            @Override
            public void accept(String str){ System.out.println(str); }};//Lambda expressions are simplified
        Consumer<String> consumer =(str)->{System.out.println(str); }; consumer.accept("Print STR"); }}Copy the code
  • Supply interface: Supplier < T> T get() An abstract method with no arguments and a return value;
/** ** supply interface */
public class SupplierInterface {
    public static void main(String[] args) {
        Supplier<String> supplier = new Supplier<String>() {
            @Override
            public String get() {
                return "Supply interface"; }};//Lambda expressions are simplified
        Supplier<String> sp =()->{return "Supply interface"; }; System.out.println(sp.get()); }Copy the code
  • Stereotyped interfacePredicate Boolean test(T T): takes arguments, but the return value type is fixed Boolean;
/** * Predicate * takes an input parameter and can only return a Boolean value for judgment */
 
public static void main(String[] args) {
    // Can be used to determine whether the string is empty
    Predicate pc = new Predicate<String>() {
        @Override
        public boolean test(String str) {
 
            returnstr.isEmpty(); }}; System.out.println(pc.test("qwew"));
 
    //Lambda expressions are simplified
    Predicate<String> pre =(str)->{return str.isEmpty(); };
    System.out.println(pre.test(""));
}

Copy the code
  • Functional interface: Function<T,R> R apply(T T);
/** * Function * returns a value */
public static void main(String[] args) {
    Function function = new Function<String.String> () {
        @Override
        public String apply(String str) {
            returnstr; }};//Lambda expressions are simplified
    Function<String.String> function2 = (str) -> {return str; };
 
    System.out.println(function2.apply("asd"));
 
}

Copy the code

The Stream flow

We can use java.util.Stream to do various operations on a collection of one or more elements. These operations may be intermediate operations or terminal operations. The terminal operation returns a result, and the intermediate operation returns a Stream.

Stream method description

forEach

The forEach() method iterates through the elements in the stream

void forEach(Consumer<? super T> action)

 List<String> list = new ArrayList<>();
        list.add("a");
        list.add("b");
        list.add("c");
        list.add("d");
        list.stream().forEach((str)->{
            System.out.println(str);
        });
 / / short
 list.stream().forEach(System.out::println);
Copy the code

Filter

Filter Filters out elements that meet the specified criteria

public static void main(args[]){
    List languages = Arrays.asList("Java"."Scala"."C++"."Haskell"."Lisp");
 
    System.out.println("Languages which starts with J :");
    filter(languages, (str)->str.startsWith("J"));
 
    System.out.println("Languages which ends with a ");
    filter(languages, (str)->str.endsWith("a"));
 
    System.out.println("Print all languages :");
    filter(languages, (str)->true);
 
    System.out.println("Print no language : ");
    filter(languages, (str)->false);
 
    System.out.println("Print language whose length greater than 4:");
    filter(languages, (str)->str.length() > 4);
}
 
public static void filter(List names, Predicate condition) {
    names.stream().filter((name) -> (condition.test(name))).forEach((name) -> {
        System.out.println(name + "");
    });
}

Copy the code

Predicate

// You can combine the Predicate with logical functions and(), or(), and xor(),
For example, to find all the four-letter names that start with J, you can combine the two Predicate classes and pass them in
Predicate<String> startsWithJ = (n) -> n.startsWith("J");
Predicate<String> fourLetterLong = (n) -> n.length() == 4;
names.stream()
    .filter(startsWithJ.and(fourLetterLong))
    .forEach((n) -> System.out.print("nName, which starts with 'J' and four letter long is : " + n));

Copy the code

limit

Filter the first n elements from the stream

Stream<T> limit(long maxSize);

// Filter out the first two elements in the stream
list.stream().limit(2).forEach(System.out::println);
Copy the code

map

The map() method maps elements in a stream to another stream

// This method requires a function-type interface to convert data of type T in the current stream into a stream of type R
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
Copy the code
 public static void main(String[] args) {
        Stream.of("1"."2"."3"."4"."5")
                .map(Integer::parseInt)
                .forEach(System.out::println);
        Stream.of(6.7.8.9.10)
                .map(String::valueOf)
                .forEach(System.out::println);
    }

Copy the code

skip

Skip the first n elements and intercept

Stream<T> skip(long n);
Copy the code

Use:

public static void main(String[] args) {
        Stream.of("a"."b"."c"."d"."a"."b"."a"."c")
                .skip(5)
                / /. Skip (1) an error
                //.skip(10)
                .forEach(System.out::println);
    }
Copy the code

concat

The concat() method, a static method in the Stream interface, merges two streams

public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) {
        Objects.requireNonNull(a);
        Objects.requireNonNull(b);

        @SuppressWarnings("unchecked")
        Spliterator<T> split = new Streams.ConcatSpliterator.OfRef<>(
                (Spliterator<T>) a.spliterator(), (Spliterator<T>) b.spliterator());
        Stream<T> stream = StreamSupport.stream(split, a.isParallel() || b.isParallel());
        return stream.onClose(Streams.composedClose(a, b));
    }

Copy the code

Use:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);

        Stream<Integer> stream1 = list.stream().filter((str) -> {
            return str > 12;
        });

        Stream<Integer> stream2 = list.stream().filter((str) -> {
            return str < 5;
        });

       Stream.concat(stream1, stream2).forEach(System.out::println); / / 13 April
Copy the code

reduce

Sum up all the data into one number

 T reduce(T identity, BinaryOperator<T> accumulator);

Copy the code

Use:

public static void main(String[] args) {
        Integer sum = Stream.of("1"."2"."3"."4"."5"."1"."1"."2")
                .map(Integer::parseInt)
                // identity: default value
                // The first time the default value is assigned to a
                // Each time after that, the last result is assigned to A, and B receives the data in the stream
                .reduce(0, (a, b) -> {
                    System.out.print("a = " + a);
                    System.out.println(" b = " + b);
                    return a + b;
                });
        System.out.println("sum = " + sum);
        // Get the maximum value:
        Integer max = Stream.of("1"."2"."3"."4"."5")
                .map(Integer::parseInt)
                .reduce(0, (a, b) -> a > b ? a : b);
                //.reduce(1, Math::max);
        System.out.println("max = "+max);
        // Count the number of occurrences of 1
        Integer count = Stream.of("1"."2"."3"."4"."5"."1"."1"."2")
                .map(s -> "1".equals(s) ? 1 : 0)
                .reduce(0.Integer::sum);
        System.out.println(count);
    }
Copy the code

max,min

Max: Obtains the maximum value

Optional<T> max(Comparator<? super T> comparator);

Copy the code

Min: obtains the minimum value

Optional<T> min(Comparator<? super T> comparator);

Copy the code

Use:

    public static void main(String[] args) {
        Optional<Integer> max = Stream.of("1"."2"."3"."4"."5")
                .map(Integer::parseInt)
                .max(Comparator.comparingInt(o -> o));
                // .max((o1,o2)->o1-o2); equivalent
        System.out.println("max = "+max.get());
        Optional<Integer> min = Stream.of("1"."2"."3"."4"."5")
                .map(Integer::parseInt)
                .min((o1,o2)->o1-o2);
        System.out.println("min = "+min.get());
    }
Copy the code

distinct

Remove duplicate elements

Stream<T> distinct();

Copy the code

Use:

 public static void main(String[] args) {
        Stream<String> distinct = Stream.of("a"."b"."c"."d"."a"."b"."a"."c")
                .distinct();
        distinct.forEach(System.out::println);

        // The equals and hashcode methods need to be overridden in the Student class to remove duplicate data
        Stream.of(new Student("Zhang".18),
                new Student("Bill".20),
                new Student("Zhang".18),
                new Student("Fifty".22),
                new Student("Bill".20))
                .distinct()
                .forEach(System.out::println);
    }
Copy the code

AllMatch, anyMatch, nonMatch

AllMatch (), anyMatch(), and nonMatch() methods to determine whether data matches specified conditions

//allMatch() : Whether all elements match conditions
boolean allMatch(Predicate<? super T> predicate);

//anyMatch() : Whether the element has any matching conditions
boolean anyMatch(Predicate<? super T> predicate);

//nonMatch() : Whether all elements do not meet the condition
boolean noneMatch(Predicate<? super T> predicate);

Copy the code

Use:

List<Integer> list = new ArrayList<>();
    list.add(13);
    list.add(12);
    list.add(8);
    list.add(4);

    boolean b1 = list.stream().allMatch((n) -> {return n > 8; });//false
    boolean b2 = list.stream().anyMatch((n) -> {return n > 8; });//true
    boolean b3 = list.stream().noneMatch((n) -> {return n > 8; });//false
Copy the code

sorted

The sorted() method sorts the data in the stream

Stream<T> sorted();

Stream<T> sorted(Comparator<? super T> comparator);

@FunctionalInterface
public interface Comparator<T> {
    int compare(T o1, T o2);
}

Copy the code

Use:

List<Integer> list = new ArrayList<>();
        list.add(13);
        list.add(12);
        list.add(8);
        list.add(4);
        
        list.stream().sorted((str1,str2)->(str1-str2)).forEach(System.out::println);
Copy the code

count

Used to count the number of elements and returns a value of type long representing the number of elements

long count();

Copy the code

Use:

    public static void main(String[] args) {
        long count = Stream.of("a"."b"."c"."d"."a"."b"."a"."c")
                .count();
        System.out.println("The number of elements is:"+count);
    }
Copy the code

peek

List<Person> lists = new ArrayList<Person>();
lists.add(new Person(1L, "p1"));
lists.add(new Person(2L, "p2"));
lists.add(new Person(3L, "p3"));
lists.add(new Person(4L, "p4"));
System.out.println(lists);

List<Person> list2 = lists.stream()
				 .filter(f -> f.getName().startsWith("p"))
                .peek(t -> {
                    System.out.println(t.getName());
                })
                .collect(Collectors.toList());
System.out.println(list2);
Copy the code

mapToInt

The mapToInt() method converts elements of type Integer in a Stream to type int

IntStream mapToInt(ToIntFunction<? super T> mapper);

Copy the code

Use:

List<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(8);
        list.add(4);
        list.add(13);
        
list.stream().mapToInt(new ToIntFunction<Integer>() {
            @Override
            public int applyAsInt(Integer value) {
                return value;
            }
        }).forEach(System.out::println);
Copy the code