The notes of the Java Foundation series are finally completed, and the end is dotted _★,°_:.☆( ̄▽ ̄)/$:.°★.

Attach the addresses of all the code: Java Base code

A summary of new Java 8 features

Improvements to Java 8

  • faster

  • Less code (added new syntax: Lambda expressions)

  • Introduce powerful Stream APl

  • Facilitate parallel

  • Minimize null pointer exceptions: Optional

  • The Nashorn engine allows JS applications to run on the JVM

  • A parallel stream is a stream that splits a piece of content into chunks of data and uses different threads to process each chunk separately. Compared with serial stream, parallel stream can greatly improve the execution efficiency of the program.

  • Java 8 is optimized for parallelism, making it easy to parallelize data. The Stream API declaratively switches between parallel and sequential streams using parallel() and sequential()

Lambda expressions

1. Overview of the Lamdba expression

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

2. Use Lambda expressions to compare before and after

Example 1: Invoke the Runable interface

@Test
public void test1(a){
    // Lambda expressions are not used
    Runnable r1 = new Runnable() {
        @Override
        public void run(a) {
            System.out.println("hello Lambda!"); }}; r1.run(); System.out.println("= = = = = = = = = = = = = = = = = = = = = = = =");
    //Lamdba expression
    Runnable r2 = () -> System.out.println("hi Lambda!");
    r2.run();
}


Copy the code

Example 2: Using the Comparator interface

@Test
public void test2(a){
    // Lambda expressions are not used
    Comparator<Integer> com1 = new Comparator<Integer>() {
        @Override
        public int compare(Integer o1, Integer o2) {
            returnInteger.compare(o1,o2); }};int compare1 = com1.compare(12.32);
    System.out.println(compare1);/ / 1
    System.out.println("= = = = = = = = = = = = = = = = = = =");

    // How to write Lambda expressions
    Comparator<Integer> com2 = (o1,o2) -> Integer.compare(o1,o2);

    int compare2 = com2.compare(54.21);
    System.out.println(compare2);/ / 1
    System.out.println("= = = = = = = = = = = = = = = = = = =");

    // Method reference
    Comparator<Integer> cpm3 = Integer::compareTo;
    int compare3 = cpm3.compare(12.12);
    System.out.println(compare3);/ / 0
}


Copy the code

3. How to use Lambda expressions

3.1 Basic syntax of Lamdba expressions

1. Example: (o1, O2) -> Integer.compare(o1, O2);

2. Format:

  • ->Lambda operator or arrow operator
  • ->Left: lambda parameter list (which is essentially the parameter list for abstract methods in the interface)
  • ->Right: lambda body (essentially the method body of the overridden abstract method)

3.2 Lamdba expression usage (including six cases)

3.2.1 Syntax Format 1: No parameter, return value

Runnable R1 = () -> {system.out.println (" Hello Lamdba! )}Copy the code

Lamdba takes a parameter but returns no value

Consumer<String> con = (String str) -> {System.out.println(str)}
Copy the code

3.2.3 Syntax Format 3: Data types can be omitted because they can be inferred by the compiler, called type inference

Consumer<String> con = (str) -> {System.out.println(str)}
Copy the code

3.2.4 Syntax Format 4: Lamdba If only one parameter is required, the parentheses can be omitted

Consumer<String> con = str -> {System.out.println(str)}
Copy the code

3.2.5 Syntax Format 5: Lamdba requires more than two parameters, multiple execution statements, and can have a return value

Comparator<Integer>com = (o1,o1) -> {
	Syste.out.println("Lamdba expression usage");
    return Integer.compare(o1,o2);
}
Copy the code

3.2.6 Syntax Format 6: When the Lamdba body has only one statement, the return and curly braces, if any, can be omitted

Comparator<Integer>com = (o1,o1) ->	Integer.compare(o1,o2);
Copy the code

Code examples:

public class LamdbaTest2 {
    // Syntax format 1: no parameter, no return value
    @Test
    public void test1(a) {
        // Lambda expressions are not used
        Runnable r1 = new Runnable() {
            @Override
            public void run(a) {
                System.out.println("Hello Lamdba"); }}; r1.run(); System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Runnable r2 = () -> {
            System.out.println("Hi Lamdba");
        };
        r2.run();
    }

    Lambda takes one argument, but returns no value.
    @Test
    public void test2(a) {
        // Lambda expressions are not used
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) { System.out.println(s); }}; con.accept("Hello Lambda!");
        System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Consumer<String> con1 = (String s) -> {
            System.out.println(s);
        };
        con1.accept("I am a Lambda");

    }

    // Data types can be omitted because they can be inferred by the compiler, called "type inference"
    @Test
    public void test3(a) {
        // Lambda expressions are not used
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) { System.out.println(s); }}; con.accept("Hello Lambda!");
        System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Consumer<String> con1 = (s) -> {
            System.out.println(s);
        };
        con1.accept("I am a Lambda");
    }

    @Test
    public void test(a){
        ArrayList<String> list = new ArrayList<>();// Type inference, using left to infer right
        int[] arr = {1.2.3.4};// Type inference, using left to infer right
    }

    If Lambda requires only one argument, the parentheses of the argument can be omitted
    @Test
    public void test4(a) {
        // Lambda expressions are not used
        Consumer<String> con = new Consumer<String>() {
            @Override
            public void accept(String s) { System.out.println(s); }}; con.accept("Hello Lambda!");
        System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Consumer<String> con1 = s -> {
            System.out.println(s);
        };
        con1.accept("I am a Lambda");
    }

    Lambda takes two or more arguments, multiple execution statements, and can have a return value
    @Test
    public void test5(a) {
        // Lambda expressions are not used
        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                System.out.println(o1);
                System.out.println(o2);
                returnInteger.compare(o1, o2); }}; System.out.println(com1.compare(23.45));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Comparator<Integer> com2 = (o1, o2) -> {
            System.out.println(o1);
            System.out.println(o2);
            return o1.compareTo(o2);
        };
        System.out.println(com2.compare(23.12));
    }

    // If the Lambda body has only one statement, the return and braces, if present, can be omitted
    @Test
    public void test6(a) {
        // Lambda expressions are not used
        Comparator<Integer> com1 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                returnInteger.compare(o1, o2); }}; System.out.println(com1.compare(23.45));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Comparator<Integer> com2 = (o1, o2) -> o1.compareTo(o2);

        System.out.println(com2.compare(23.12));
    }
    @Test
    public void test7(a){
        // Lambda expressions are not used
        Consumer<String> con1 = new Consumer<String>() {
            @Override
            public void accept(String s) { System.out.println(s); }}; con1.accept("hi!");
        System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Consumer<String> con2 = s -> System.out.println(s);
        con2.accept("hello"); }}Copy the code

3.3 Summary of use of Lambda expressions

  • ->Left: The argument types of the lambda parameter list can be omitted (type inference); If the lambda parameter list has only one argument, one is pair(a)You can also omit
  • ->Right: lambda body should use a pair{}The parcel; If the lambda body has only one execution statement (possiblyreturnStatement), omit the pair{}returnThe keyword

4. Lamdba expression summary

  • The essence of Lambda expressions: as instances of functional interfaces
  • An interface that declares only one abstract method is called a functional interface. We can use it on one interface@FunctionalInterfaceAnnotations, to check if it is a functional interface.
  • So everything previously represented as anonymous implementation classes can now be written as Lambda expressions.

2. Functional interfaces

1. Overview of functional interfaces

  • An interface that contains only one abstract method is called a functional interface.

  • Objects of this interface can be created using Lambda expressions. If a Lambda expression throws a checked exception (that is, a non-runtime exception), the exception needs to be declared on the abstract method of the target interface.

  • You can use the @functionalinterface annotation on an interface to check if it is a FunctionalInterface. Javadoc also contains a declaration that the interface is a functional interface.

  • The essence of Lambda expressions: as instances of functional interfaces

  • Java 8’s rich functional interfaces are defined under the java.util.function package

Custom functional interfaces

@FunctionalInterface
public interface MyInterface {
    void method1(a);
}
Copy the code

3. Java built-in functional interfaces

3.1 Four core functional interfaces

Application, for example,

public class LambdaTest3 {
    
      
        void accept(T T)
      
    @Test
    public void test1(a) {
        // Lambda expressions are not used
        Learn("java".new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("Learn what? "+ s); }}); System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Learn("html", s -> System.out.println("Learn what? " + s));

    }

    private void Learn(String s, Consumer<String> stringConsumer) {
        stringConsumer.accept(s);
    }

    
      
        T get()
      
    @Test
    public void test2(a) {
        // Lambdabiaodas is not used
        Supplier<String> sp = new Supplier<String>() {
            @Override
            public String get(a) {
                return new String("I have something to offer."); }}; System.out.println(sp.get()); System.out.println("= = = = = = = = = = = = = = = = = = = =");
        // Use Lambda expressions
        Supplier<String> sp1 = () -> new String("I can offer things through lambda.");
        System.out.println(sp1.get());
    }

    Function
      
        R apply(T T)
      ,r>
    @Test
    public void test3(a) {
        // Use Lambda expressions
        Employee employee = new Employee(1001."Tom".45.10000);

        Function<Employee, String> func1 =e->e.getName();
        System.out.println(func1.apply(employee));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        Function<Employee,String>func2 = Employee::getName;
        System.out.println(func2.apply(employee));

    }

    // Predicate
      
        Boolean test(T T)
      
    @Test
    public void test4(a) {
        // Use anonymous inner classes
        Function<Double, Long> func = new Function<Double, Long>() {
            @Override
            public Long apply(Double aDouble) {
                returnMath.round(aDouble); }}; System.out.println(func.apply(10.5));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use Lambda expressions
        Function<Double, Long> func1 = d -> Math.round(d);
        System.out.println(func1.apply(12.3));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        Function<Double,Long>func2 = Math::round;
        System.out.println(func2.apply(12.6)); }}Copy the code

3.2 Other functional interfaces

4. Use summaries

4.1 When to use lambda expressions?

Lambda expressions can be used when a functional interface needs to be instantiated.

4.2 When to use a given functional interface?

If we need to define a functional interface in our development, we will first see if the functional interface provided in the existing JDK provides the functional interface that meets our requirements. If yes, you can call it directly. You do not need to customize it.

3. Method reference

1. Overview of method references

Method references can be thought of as deeper expressions of Lambda expressions. In other words, a method reference is a Lambda expression, an instance of a functional interface that points to a method by its name.

2. Usage scenarios

When an operation to be passed to a Lambda body already implements a method, you can use a method reference!

3. Use format

Class (or object) :: method name

4. Usage

  • Case 1 object :: non-static method

  • Case 2: static methods

  • Case 3: non-static methods

5. Usage requirements

  • Require that the parameter list and return value types of the abstract methods in the interface be the same as those of the methods referenced by the methods! (For case 1 and case 2)
  • When the first argument to a functional interface method is the caller that needs to reference the method, and the second argument is the argument (or no argument) that needs to reference the method:ClassName::methodName(For case 3)

6. Usage suggestions

If providing instances to functional interfaces fits the usage scenario for method references, you can consider using method references to provide instances to functional interfaces. Lambda expressions can also be used if method references are unfamiliar.

7. Examples

public class MethodRefTest {

    // Object :: instance method
    //Consumer void accept(T T)
    // void println(T T)
    @Test
    public void test1(a) {
        // Use Lambda expressions
        Consumer<String> con1 = str -> System.out.println(str);
        con1.accept("China");
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        PrintStream ps = System.out;
        Consumer con2 = ps::println;
        con2.accept("China");

    }

    //Supplier T get()
    //Employee String getName()
    @Test
    public void test2(a) {
        // Use Lambda expressions
        Employee emp = new Employee(1001."Bruce".34.600);
        Supplier<String> sup1 = () -> emp.getName();
        System.out.println(sup1.get());
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        Supplier sup2 = emp::getName;
        System.out.println(sup2.get());


    }

    // Case 2: class :: static method
    // int compare(T t1,T t2)
    // int compare(T t1,T t2)
    @Test
    public void test3(a) {
        // Use Lambda expressions
        Comparator<Integer> com1 = (t1, t2) -> Integer.compare(t1, t2);
        System.out.println(com1.compare(32.45));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        Comparator<Integer> com2 = Integer::compareTo;
        System.out.println(com2.compare(43.34));
    }

    //Function R apply(T T)
    // Long round(Double d)
    @Test
    public void test4(a) {
        // Use anonymous inner classes
        Function<Double, Long> func = new Function<Double, Long>() {
            @Override
            public Long apply(Double aDouble) {
                returnMath.round(aDouble); }}; System.out.println(func.apply(10.5));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use Lambda expressions
        Function<Double, Long> func1 = d -> Math.round(d);
        System.out.println(func1.apply(12.3));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        Function<Double, Long> func2 = Math::round;
        System.out.println(func2.apply(12.6));


    }

    // Case 3: class :: instance method
    // int comapre(T t1,T t2)
    // int t1.compareTo(t2)
    @Test
    public void test5(a) {
        // Use Lambda expressions
        Comparator<String> com1 = (s1, s2) -> s1.compareTo(s2);
        System.out.println(com1.compare("abd"."aba"));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        Comparator<String> com2 = String::compareTo;
        System.out.println(com2.compare("abd"."abc"));
    }

    // Boolean test(T t1, T t2) in BiPredicate;
    //String Boolean t1.equals(t2)
    @Test
    public void test6(a) {
        // Use Lambda expressions
        BiPredicate<String, String> pre1 = (s1, s2) -> s1.equals(s2);
        System.out.println(pre1.test("abc"."abc"));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method references
        BiPredicate<String, String> pre2 = String::equals;
        System.out.println(pre2.test("abc"."abd"));

    }

    // Function R apply(T T)
    // Employee String getName();
    @Test
    public void test7(a) {
        // Use Lambda expressions
        Employee employee = new Employee(1001."Tom".45.10000);

        Function<Employee, String> func1 =e->e.getName();
        System.out.println(func1.apply(employee));
        System.out.println("= = = = = = = = = = = = = = = = = = = =");

        // Use method referencesFunction<Employee,String>func2 = Employee::getName; System.out.println(func2.apply(employee)); }}Copy the code

Constructor and array references

1. Use format

Method reference: Class name ::new

Array reference: Array type [] :: new

2. Usage requirements

2.1 Constructor references

Similar to method references, the parameter list of the abstract method of a functional interface is the same as the parameter list of the constructor. The return value type of an abstract method is the type of the class to which the constructor belongs

2.2 Array Reference

You can think of an array as a special class and write it as a constructor reference.

3. Examples

3.1 Constructor references

// Constructor reference
//Supplier T get()
@Test
public void test1(a) {
    // Use anonymous inner classes
    Supplier<Employee> sup = new Supplier<Employee>() {
        @Override
        public Employee get(a) {
            return newEmployee(); }}; System.out.println(sup.get());// Use Lambda expressions
    System.out.println("= = = = = = = = = = = = = = = = = = = =");
    Supplier<Employee> sup1 = () -> new Employee(1001."Tom".43.13333);
    System.out.println(sup1.get());

    // Use method references
    Supplier<Employee> sup2 = Employee::new;
    System.out.println(sup2.get());

}

//Function R apply(T T)
@Test
public void test2(a) {
    // Use Lambda expressions
    Function<Integer, Employee> func1 = id -> new Employee(id);
    Employee employee = func1.apply(1001);
    System.out.println(employee);
    System.out.println("= = = = = = = = = = = = = = = = = = = =");

    // Use method references
    Function<Integer, Employee> func2 = Employee::new;
    Employee employee1 = func2.apply(1002);
    System.out.println(employee1);

}

BiFunction R apply(T T,U U)
@Test
public void test3(a) {
    // Use Lambda expressions
    BiFunction<Integer, String, Employee> func1 = (id, name) -> new Employee(id, name);
    System.out.println(func1.apply(1001."Tom"));
    System.out.println("= = = = = = = = = = = = = = = = = = = =");

    // Use method references
    BiFunction<Integer, String, Employee> func2 = Employee::new;
    System.out.println(func2.apply(1002."Jarry"));
}
Copy the code

3.2 Array Reference

// Array reference
//Function R apply(T T)
@Test
public void test4(a) {
    Function<Integer, String[]> func1 = length -> new String[length];
    String[] arr1 = func1.apply(5);
    System.out.println(Arrays.toString(arr1));

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

    // Use method references
    Function<Integer,String[]>func2=String[]::new;
    String[] arr2 = func2.apply(10);
    System.out.println(Arrays.toString(arr2));
}
Copy the code

Fifth, StreamAPI

1. Overview of Stream API

  • StreamI’m concerned with operations on data, andCPUTo deal with. Collections are concerned with data storage, dealing with memory;
  • Java 8 provides oneapi, using this setapiData in memory can be filtered, sorted, mapped, reduced and other operations. Similar to thesqlOperations related to tables in a database.
  • StreamIs a data channel used to manipulate sequences of elements generated by data sources (collections, arrays, and so on).“Collections are about data, streams are about computation!”

Points for attention:

① The Stream does not store elements by itself.

② Stream does not change the source object. Instead, they return a new Stream holding the result.

③ The Stream operation is delayed. This means they wait until they need results.

2. Stream uses the flow

Instantiation of Stream

② A series of intermediate operations (filtering, mapping,…)

③ Terminate operation

Points to note in using the process:

  • An intermediate chain of operations that processes data from the data source
  • Once the termination operation is performed, the intermediate operation chain is executed and the result is produced. After that, it won’t be used again

3. Usage

3.1 Step 1 Create a Stream

3.1.1 Creation Method 1: Using a Collection

Java 8’s Collection interface has been extended to provide two methods for retrieving streams:

  • default Stream\<E> stream(): Returns a sequential stream
  • default Stream\<E> parallelStream(): Returns a parallel stream

3.1.2 Creation Method 2: Use an array

The static stream() method of Arrays in Java 8 fetches array streams

  • callArraysOf the classstatic\<T> Stream\<T> stream(T[] array): Returns a stream
  • An overloaded form that can handle arrays corresponding to primitive types:
    • Public static stream stream (int[] array)
    • Public static LongStream stream (long[] array)
    • Public static DoubleStream stream (double[] array)

3.1.3 Creation method 3: Through the of() method of Stream

You can call the Stream class static method of() to create a Stream by displaying values. Can be used to receive any number of parameters

  • public static \<T>Stream\<T> of(T... values): Returns a stream

3.1.4 Creation Method 4: Create an infinite Stream

  • Iterations:public static\<T> Stream\<T> iterate(final T seed, final UnaryOperator\<T> f)
  • Generation:public static\<T> Stream\<T> generate(Supplier\<T> s)

Code examples:

public class StreamAPITest1 {
    // Create a Stream through a collection
    @Test
    public void test1(a) {
        List<Employee> employees = EmployeeData.getEmployees();
        //efault Stream
      
        Stream () : returns a sequential Stream
      
        Stream<Employee> stream = employees.stream();

        //default Stream
      
        parallelStream() : returns a parallelStream
      
        Stream<Employee> employeeStream = employees.parallelStream();
    }

    // Create a Stream through an array
    @Test
    public void test2(a) {
        int[] arrs = {1.2.3.6.2};
        // Call the ArrayClass static 
      
        Stream
       
         Stream (T[] array): returns a Stream
       
      
        IntStream stream = Arrays.stream(arrs);

        Employee e1 = new Employee(1001."Tom");
        Employee e2 = new Employee(1002."Jerry");
        Employee[] employees = {e1, e2};
        Stream<Employee> stream1 = Arrays.stream(employees);
    }

    // Create a Stream through a Stream of()
    @Test
    public void test3(a) {
        Stream<Integer> integerStream = Stream.of(12.34.45.65.76);
    }

    // Create a Stream
    @Test
    public void test4(a) {

        / / iteration
        //public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)
        // Iterate over the first 10 even numbers
        Stream.iterate(0, t -> t + 2).limit(10).forEach(System.out::println);

        / / generated
        //public static<T> Stream<T> generate(Supplier<T> s)
        Stream.generate(Math::random).limit(10).forEach(System.out::println); }}Copy the code

3.2 Intermediate Operations in Step 2

Multiple intermediate operations can be joined together to form a pipeline that does not perform any processing unless termination is triggered on the pipeline! When the operation terminates, it is processed all at once, which is called lazy evaluation.

3.2.1 Screening and sectioning

Code examples:

//1- Filter and slice. Note that the Stream is closed after the termination operation, and needs to be created again
@Test
public void test1(a){
    List<Employee> employees = EmployeeData.getEmployees();
    // Filter (Predicate P) - Receives Lambda, excludes certain elements from the stream.
    Stream<Employee> employeeStream = employees.stream();
    Select * from employee table where salary > 7000
    employeeStream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);

    //limit(n) -- truncates the stream so that it does not exceed a given number of elements.
    employeeStream.limit(3).forEach(System.out::println);
    System.out.println();

    //skip(n) -- Skip the element and return a stream with the first n elements thrown away. If there are less than n elements in the stream, an empty stream is returned. And limit (n) complement each other
    employeeStream.skip(3).forEach(System.out::println);
    //distinct() -- Filter to remove duplicate elements by hashCode() and equals() of the elements generated by the stream
    employees.add(new Employee(1010."Liu Qingdong".56.8000));
    employees.add(new Employee(1010."Liu Qingdong".56.8000));
    employees.add(new Employee(1010."Liu Qingdong".56.8000));
    employees.add(new Employee(1010."Liu Qingdong".56.8000));

    employeeStream.distinct().forEach(System.out::println);
}


Copy the code

3.2.2 mapping

Code examples:

/ / 2 - mapping
@Test
public void test2(a){
    List<String> list = Arrays.asList("aa"."bb"."cc"."dd");
    //map(Function f) -- Takes a Function as an argument to convert elements to other forms or extract information. This Function is applied to each element and maps it to a new element.
    list.stream().map(str -> str.toUpperCase()).forEach(System.out::println);

    // Exercise 1: Get the names of employees whose names are longer than 3.
    List<Employee> employees = EmployeeData.getEmployees();
    Stream<String> nameStream = employees.stream().map(Employee::getName);
    nameStream.filter(name -> name.length() >3).forEach(System.out::println);
    System.out.println();
    // Exercise 2: Implement the flatMap() intermediate method using the map() intermediate operation
    Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest2::fromStringToStream);
    streamStream.forEach(s ->{
        s.forEach(System.out::println);
    });
    System.out.println();
    //flatMap(Function f) -- Takes a Function as an argument, replaces every value in the stream with another stream, and concatenates all streams into a single stream.
    Stream<Character> characterStream = list.stream().flatMap(StreamAPITest2::fromStringToStream);
    characterStream.forEach(System.out::println);

}
// Convert a collection of multiple characters in a string to an instance of the corresponding Stream
public static Stream<Character>fromStringToStream(String str){
    ArrayList<Character> list = new ArrayList<>();
    for (Character c :
         str.toCharArray()) {
        list.add(c);
    }
    return list.stream();
}
The map() and flatMap() methods are similar to the add() and addAll() methods in the List
@Test
public void test(a){
    ArrayList<Object> list1 = new ArrayList<>();
    list1.add(1);
    list1.add(2);
    list1.add(3);
    list1.add(4);

    ArrayList<Object> list2 = new ArrayList<>();
    list2.add(5);
    list2.add(6);
    list2.add(7);
    list2.add(8);

    list1.add(list2);
    System.out.println(list1);//[1, 2, 3, 4, [5, 6, 7, 8]]
    list1.addAll(list2);
    System.out.println(list1);//[1, 2, 3, 4, [5, 6, 7, 8], 6, 7, 8]

}


Copy the code

3.2.3 sorting

Code examples:

/ / 3 - sort
@Test
public void test3(a){
    Sorted () -- sorted naturally
    List<Integer> list = Arrays.asList(12.34.54.65.32);
    list.stream().sorted().forEach(System.out::println);

    Employee does not implement the Comparable interface
    List<Employee> employees = EmployeeData.getEmployees();
    employees.stream().sorted().forEach(System.out::println);

    Sorted (Comparator com) -- Custom sorted
    List<Employee> employees1 = EmployeeData.getEmployees();
    employees1.stream().sorted((e1,e2)->{
        int ageValue = Integer.compare(e1.getAge(), e2.getAge());
        if(ageValue ! =0) {return ageValue;
        }else {
            return -Double.compare(e1.getSalary(),e2.getSalary());
        }

    }).forEach(System.out::println);
}


Copy the code

3.3 Step 3 Terminate the operation

  • Terminal operations generate results from the pipeline of streams. The result can be any value that is not a stream, such as List, Integer, or even void

  • After a stream terminates, it cannot be used again.

3.3.1 Matching and Searching

Code examples:

//1- match and find
@Test
public void test1(a){
    List<Employee> employees = EmployeeData.getEmployees();

    //allMatch(Predicate P) -- Checks if all elements match.
    // Exercise: Are all employees older than 18
    boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
    System.out.println(allMatch);
    //anyMatch(Predicate P) - Checks if at least one element matches.
    // Exercise: Is there any employee whose salary is greater than 5000
    boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 5000);
    System.out.println(anyMatch);

    //noneMatch(Predicate P) - Checks if there are no matching elements.
    // Exercise: Is there any employee whose surname is "Lei"
    boolean noneMatch = employees.stream().noneMatch(e -> e.getName().startsWith("Ray"));
    System.out.println(noneMatch);

    //findFirst -- Returns the first element
    Optional<Employee> first = employees.stream().findFirst();
    System.out.println(first);

    //findAny -- Returns any element in the current stream
    Optional<Employee> employee = employees.parallelStream().findAny();
    System.out.println(employee);


}

@Test
public void test2(a){
    List<Employee> employees = EmployeeData.getEmployees();
    // count -- Returns the total number of elements in the stream
    long count = employees.stream().filter(e -> e.getSalary()>5000).count();
    System.out.println(count);

    // Max (Comparator c) -- returns the maximum value in the stream
    // Exercise: Return the highest salary
    Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
    Optional<Double> maxSalary = salaryStream.max(Double::compareTo);
    System.out.println(maxSalary);

    //min(Comparator c) -- returns the minimum value in the stream
    // Exercise: return minimum wage employee
    Optional<Double> minSalary = employees.stream().map(e -> e.getSalary()).min(Double::compareTo);
    System.out.println(minSalary);

    ForEach (Consumer C) -- internal iteration
    employees.stream().forEach(System.out::println);
    System.out.println();
    // Use the collection traversal operation
    employees.forEach(System.out::println);

}


Copy the code

3.3.2 rainfall distribution on 10-12 reduction

Note: The connection between Map and Reduce is commonly known as the map-reduce mode, which is famous for Google’s use of it for web searches

Code examples:

/ / 2 - reduction
@Test
public void test3(a){
    //reduce(T identity, BinaryOperator) - Can combine elements ina stream repeatedly to get a value. Return T
    Exercise 1: Calculate the sum of the natural numbers 1-10
    List<Integer> list = Arrays.asList(1.2.3.4.5.6.7.8.9.10);
    Integer sum = list.stream().reduce(0, Integer::sum);
    System.out.println(sum);

    //reduce(BinaryOperator) - Can combine elements in the stream repeatedly to get a value. Returns the Optional < T >
    // Exercise 2: Calculate the sum of the salaries of all employees in the company
    List<Employee> employees = EmployeeData.getEmployees();
    Optional<Double> sumSalary = employees.stream().map(e -> e.getSalary()).reduce(Double::sum);
    System.out.println(sumSalary);

}


Copy the code

3.3.3 collection

The implementation of methods in the Collector interface determines how collected operations (such as collecting lists, sets, maps) are performed on streams

The Collectors class provides many static methods. You can easily create common collector instances. The following table lists the methods and instances.

Code examples:

/ / 3 - collection
@Test
public void test4(a){
    Collect (Collector C) -- Convert the stream to another form. Receives an implementation of the Collector interface, a method for summarizing elements in a Stream
    // Exercise 1: Find employees whose salaries are greater than 6000 and return a List or Set
    List<Employee> employees = EmployeeData.getEmployees();
    List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());

    employeeList.forEach(System.out::println);
    System.out.println();
    Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
    employeeSet.forEach(System.out::println);
}


Copy the code

The use of Optional classes

1. Overview of the OPtional class

  • Created to solve the null pointer problem in Java!
  • Optional < T > class (Java. Util. Optional)Is a container class that holds typesTRepresents that the value exists. Or just savenull, indicating that the value does not exist. The original usenullIndicates that a value does not exist, nowOptionalCan better express this concept. Null-pointer exceptions can also be avoided.

2. Methods provided by the Optional class

The Optional class provides a number of ways to eliminate the need to realistically perform null-value checks.

2.1 Method for creating Optional class objects

  • Optional.of(T t): Create aOptionalInstance,tMust be non-empty;
  • Optional.empty(): Creates an emptyOptionalThe instance
  • Optional.ofNullable(T t):tCan I do fornull

2.2 Determine whether the Optional container contains objects

  • Boolean isPresent() : Checks whether an object is included

  • void ifPresent(Consumer
    consumer) : If there is a value, the implementation code for the consumer interface is executed and the value is passed to it as an argument.

2.3 Obtaining the object of the Optional container

  • T get() : Returns the value if the calling object contains it, otherwise throws an exception

  • T orElse(T other) : Returns a value if there is one, otherwise returns the specified other object

  • T orElseGet(Supplier
    other) : returns a value if there is one, otherwise returns an object provided by the Supplier interface implementation.

  • T orElseThrow(Supplier
    exceptionSupplier) : Returns a value if there is one, otherwise throws an exception provided by the Supplier interface implementation.

2.4 Combination use

  • of()get()Method is used together to make it clear that the object is not empty
  • ofNullable()orElse()When used in conjunction, the object is not null

3. Application Examples

public class OptionalTest {
    @Test
    public void test1(a) {
        //empty(): The value inside the created Optional object is null
        Optional<Object> op1 = Optional.empty();
        if(! op1.isPresent()){//Optional Indicates whether the encapsulated data contains data
            System.out.println("Data is empty");
        }
        System.out.println(op1);
        System.out.println(op1.isPresent());

        // Get () fails if Optional encapsulates an empty value. Otherwise, value is returned if value is not null.
        System.out.println(op1.get());
    }
    @Test
    public void test2(a){
        String str = "hello";
// str = null;
        //of(T T): encapsulates data T to generate an Optional object. T must be non-null, otherwise an error is reported.
        Optional<String> op1 = Optional.of(str);
        // Get () is usually used with the of() method. Used to get the internal encapsulated data value
        String str1 = op1.get();
        System.out.println(str1);
    }
    @Test
    public void test3(a){
        String str ="Beijing";
        str = null;
        //ofNullable(T T) : encapsulates the value assigned by T to Optional. I don't need t to be non-empty
        Optional<String> op1 = Optional.ofNullable(str);
        System.out.println(op1);
        //orElse(T t1): returns the value if the value inside Optional is not empty. if
        // if value is null, t1 is returned.
        String str2 = op1.orElse("shanghai"); System.out.println(str2); }}Copy the code

Use the Optional class to avoid null-pointer exceptions

public class GirlBoyOptionalTest {

    // Use the original method for non-null testing
    public String getGrilName1(Boy boy){
        if(boy ! =null){
            Girl girl = boy.getGirl();
            if(girl ! =null) {returngirl.getName(); }}return null;
    }
    // Use the Optional class getGirlName() for a non-null test
    public String getGirlName2(Boy boy){
        Optional<Boy> boyOptional = Optional.ofNullable(boy);
        // "boy1" = "boy1" = "boy1"
        Boy boy1 = boyOptional.orElse(new Boy(new Girl("Dilieba")));

        Girl girl = boy1.getGirl();
        // Girl1 must not be empty,girl is empty return "Gulinaza"
        Optional<Girl> girlOptional = Optional.ofNullable(girl);
        Girl girl1 = girlOptional.orElse(new Girl(gulinaza));

        return girl1.getName();
    }

    // Test manual write control detection
    @Test
    public void test1(a){

        Boy boy = null;
        System.out.println(getGrilName1(boy));

        boy = new Boy();
        System.out.println(getGrilName1(boy));

        boy = new Boy(new Girl("Yang"));
        System.out.println(getGrilName1(boy));
    }
    // Tests control checks written with the Optional class
    @Test
    public void test2(a){
        Boy boy = null;
        System.out.println(getGirlName2(boy));

        boy = new Boy();
        System.out.println(getGirlName2(boy));

        boy = new Boy(new Girl("Yang")); System.out.println(getGirlName2(boy)); }}Copy the code

7. Improved support for reflection

Improved object creation, object assignment, and reflection object creation time

Code examples:

public class testReflection {
    // Loop 1 billion times
    private static final int loopCnt = 1000 * 1000 * 1000;

    public static void main(String[] args) throws InvocationTargetException, NoSuchMethodException, InstantiationException, IllegalAccessException {
        // Print the JDK version
        System.out.println("java version is" + System.getProperty("java.version"));
        creatNewObject();
        optionObject();
        reflectCreatObject();
    }

    / / person objects
    static class Person {
        private Integer age = 20;

        public Integer getAge(a) {
            return age;
        }

        public void setAge(Integer age) {
            this.age = age; }}// Create a new object each time
    public static void creatNewObject(a) {
        long startTime = System.currentTimeMillis();
        for (int i = 0; i < loopCnt; i++) {
            Person person = new Person();
            person.setAge(30);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time required to loop through object creation a billion times:" + (endTime - startTime));
    }

    // Assign to the same object
    public static void optionObject(a) {
        long startTime = System.currentTimeMillis();
        Person p = new Person();
        for (int i = 0; i < loopCnt; i++) {
            p.setAge(10);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time required to loop a billion times to assign to the same object:" + (endTime - startTime));
    }

    // Create objects by reflection
    public static void reflectCreatObject(a) throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        long startTime = System.currentTimeMillis();
        Class<Person> personClass = Person.class;
        Person person = personClass.newInstance();
        Method setAge = personClass.getMethod("setAge", Integer.class);
        for (int i = 0; i < loopCnt; i++) {
            setAge.invoke(person, 90);
        }
        long endTime = System.currentTimeMillis();
        System.out.println("Time required to loop a billion reflections to create an object:"+ (endTime - startTime)); }}Copy the code

When the compile level is JDK8

Java version is 1.8.0_201 Loop 1 billion times time to create an object: 9 loop 1 billion times time to assign a value to the same object: 59 loop 1 billion reflection time to create an object: 2622Copy the code

When the compile level is JDK7

Java Version is 1.7 Loop a billion times time required to create an object: 6737 loop a billion times time required to assign a value to the same object: 3394 loop a billion reflection time required to create an object: 293603Copy the code