New features in Java 8

1, New Java 8 features
1. New features
Interface changes
Third generation datetime API
HashMap underlying changes
...
Lambda expression
StreamAPI
Optional class

2. Lambda expression is a new syntax sugar, which is the syntax that makes Java start to support "functional programming".
Java used to say that it is an object-oriented programming language. Almost all operations are based on objects, "everything is an object",
If a variable or parameter is a reference data type, it must be assigned an object.

In development, sometimes we don't care about the object. We care about the function of a method of the object. The method body code is actually the implementation of the function.
According to the object-oriented programming idea, in order to pass this code, it is a little verbose to need to new an object.

Functional programming idea: transfer functions as data

public class TestJava8 {
    @Test
    public void test06(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};
        //You want to sort this array, case insensitive
        //There is a sort method for calling the Arrays tool class
        Arrays.sort(arr);//It is case sensitive because this method calls the compareTo method of element type String to sort
        System.out.println(Arrays.toString(arr));//[Chai, Hi, Jock, atguigu, hello, world]

        Arrays.sort(arr, String::compareToIgnoreCase);
        System.out.println(Arrays.toString(arr));//[atguigu, Chai, hello, Hi, Jock, world]
    }

    @Test
    public void test05(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};
        //You want to sort this array, case insensitive
        //There is a sort method for calling the Arrays tool class
        Arrays.sort(arr);//It is case sensitive because this method calls the compareTo method of element type String to sort
        System.out.println(Arrays.toString(arr));//[Chai, Hi, Jock, atguigu, hello, world]

        Arrays.sort(arr, (o1, o2) -> o1.compareToIgnoreCase(o2));
        System.out.println(Arrays.toString(arr));//[atguigu, Chai, hello, Hi, Jock, world]
    }

    @Test
    public void test04(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};
        //You want to sort this array, case insensitive
        //There is a sort method for calling the Arrays tool class
        Arrays.sort(arr);//It is case sensitive because this method calls the compareTo method of element type String to sort
        System.out.println(Arrays.toString(arr));//[Chai, Hi, Jock, atguigu, hello, world]

        Arrays.sort(arr, new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareToIgnoreCase(o2);
            }
        });
        System.out.println(Arrays.toString(arr));//[atguigu, Chai, hello, Hi, Jock, world]
    }

    @Test
    public void test03(){
        //Requirements: start a thread by implementing the Runnable interface and print "hello"“
        new Thread(() ->System.out.println("hello")).start();
    }

    @Test
    public void test02(){
        //Requirements: start a thread by implementing the Runnable interface and print "hello"“
        new Thread(new Runnable() {
            @Override
            public void run() {
                System.out.println("hello");
            }
        }).start();
    }

    @Test
    public void test01(){
        //Requirements: start a thread by implementing the Runnable interface and print "hello"“
        MyRunnable my = new MyRunnable();
        Thread t = new Thread(my);
        t.start();
    }
}
class MyRunnable implements Runnable{
    @Override
    public void run() {
        System.out.println("hello");
    }
}

2, Functional interface
The idea of functional programming is introduced into Java, but it is only supported in some cases.
Lambda expressions are used only for functional interfaces.

1. A functional interface is an interface where the SAM interface (Single Abstract Method) has a unique abstract method.

Recall the interface learned before:

1)java.lang.Runnable: 
        Abstract method: public abstract void run();
(2)java.util.Comparator<T>
        Abstract method:    int compare(T o1, T o2);

        from Comparator<T>There is one in the interface boolean equals(Object obj);,Forms are also like abstract methods,
        But it does not require us to achieve Comparator<T>The class of the interface is forcibly overridden because the implementation class defaults from Object Inherited a equals Method.
        But it suggests that we rewrite it equals method. hope equals Implementation and of method compare The implementation of the method is logically consistent.
        For example: Student Class has overrides equals Method, according to id To compare, I think two id The same student object is the same student object,
            Student Class has one Comparator Comparator for StudentComparator,Its implementation Comparator<T>Interfaces, rewriting compare method,
            This method says two students' grades score If they are equal, they return 0, which means they are "equal" objects.

            If we put the students in TreeSet In, an ordered set.
(3)java.lang.Comparable<T>
        Abstract method: int compareTo(T o);
 (4)java.lang.Iterable<T>  : Implement it, support foreach ergodic
         Abstract method: Iterator<T> iterator();
 (5)java.util.Iterator<T> Not a functional interface because there are multiple abstract methods
        Abstract method:
            boolean hasNext();
            E next();
 (6)java.io.Serializable: Not a functional interface because there are no abstract methods
 (7)java.lang.Cloneable: Not a functional interface because there are no abstract methods
 (8)Collection,List,Set,Map Neither, because there are multiple abstract methods
 (9)java.io.FileFilter
        Abstract method:
            boolean accept(File pathname);

Summary: among the previously learned interfaces, those that meet the requirements of functional interfaces
    java.lang.Runnable,java.util.Comparator<T>,java.lang.Comparable<T>,java.lang.Iterable<T>,java.io.FileFilter

2. It is recommended to use Lambda expression for interfaces that meet the characteristics of functional interfaces and are marked with @ FunctionalInterface annotation.
  Among the above interfaces that meet the characteristics of functional interfaces, those marked with @ FunctionalInterface annotation are:
  java.lang.Runnable
  java.util.Comparator<T>
  java.io.FileFilter

The Java. Lang. comparable < T > interface is not marked with @ FunctionalInterface annotation, because its implementation class is usually the type of element to be compared,
For example, the Student class itself implements this interface. This class is rich in information. Generally, it will not only focus on the compareTo method.
In the scenario where we use Lambda expressions, we usually focus only on the constants of the implementation of the abstract methods of the interface.

The Java. Lang. Iterable < T > interface is also not marked with @ FunctionalInterface annotation, because its implementation classes are usually containers, ArrayList s, etc,
It is also impossible to focus on iterator < T > iterator(); This is a method. We need to pay more attention to methods such as add.

Summary: there are only three learned interfaces. You can use Lambda expressions. Others are not recommended for the time being.

public class TestFunctionalInterface {
    public static void main(String[] args) {
        //TreeSet features: orderly (in order of size) and non repeatable
        TreeSet<Student> set = new TreeSet<>(new Comparator<Student>() {
           @Override
            public int compare(Student o1, Student o2) {
                return o1.getScore() - o2.getScore();
            }//FALSE


 /*           @Override
            public int compare(Student o1, Student o2) {
                int result = o1.getScore() - o2.getScore();
                return result == 0 ? o1.getId() - o2.getId(): result;
            }*/
        });

        set.add(new Student(1,"Zhang San",86));
        set.add(new Student(1,"Zhang San",86));
        set.add(new Student(2,"Li Si",86));

        System.out.println(set);//[Student{id=1, name = 'Zhang San', score=86}]
    }
}
class Student{
    private int id;
    private String name;
    private int score;

    public Student(int id, String name, int score) {
        this.id = id;
        this.name = name;
        this.score = score;
    }

    public int getId() {
        return id;
    }

    public void setId(int id) {
        this.id = id;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "id=" + id +
                ", name='" + name + '\'' +
                ", score=" + score +
                '}';
    }

    /*@Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Student student = (Student) o;
        return id == student.id; //In order to highlight the problem, only id is deliberately selected
    }

    @Override
    public int hashCode() {
        return Objects.hash(id);
    }*/
}

3, Lambda expression
1. Grammatical structure
    ( Parameter list of Lambda expression - > {Lambda body}

explain:
(1) - >: called arrow operator or Lambda operator
    It is composed of minus sign and greater than sign, and there can be no space in the middle
(2)  ( The formal parameter list of lambda expression), which is actually the formal parameter list of the abstract method of the functional interface that your lambda expression is intended to target
    For example, Lambda expressions are used for the java.lang.Runnable interface, and the formal parameter list of Lambda expressions is ()
            Because the abstract method void run() of the java.lang.Runnable interface

          Lambda expression is used for the Java. Util. Comparator < T > interface. The formal parameter list of lambda expression is (T t1, T t2)
            Because the abstract method int compare(T t1, T t2) of the Java. Util. Comparator < T > interface


          Lambda expressions are used for the Java. Util. Function. Consumer < T > interface. The formal parameter list of lambda expressions is (T)
            Because   Abstract method void accept (T) of Java. Util. Function. Consumer < T > interface
(3) {Lambda body}, which is actually the method body you implement this abstract method

2. Lambda expressions are used to assign values to variables / formal parameters of functional interfaces

3. Lambda expressions can be simplified
(1) When {Lambda body} has only one statement, you can omit {} and the following statement;
(2) When {Lambda body} has only one statement, you can omit {} and the following statement;. If this is a return statement, you should also omit return
(3) When the parameter type of the parameter list (parameter list of Lambda expression) is known or can be inferred automatically according to the generic type, the type can be omitted
(4) If the type of the formal parameter list of (the formal parameter list of Lambda expression) is omitted and there is only one formal parameter, then () can be omitted,
        () cannot be omitted if the formal parameter list is more than one parameter
        If the formal parameter list is an empty parameter (), then () cannot be omitted

public class TestLambda {
    @Test
    public void test04(){
        //Requirements: List "D: \ to"_ Student \ Shang Silicon Valley_ 210728Java_ Chai Linyan_ . exe file in the directory "JavaSE \ pre installed software"
        File dir = new File("D:\\to_student\\Shang Silicon Valley_210728Java_Chai Linyan_JavaSE\\Pre installed software");

        /*
        Call the public file [] listfiles (filefilter) method of java.io.File class
        The formal parameter of this method is (FileFilter filter). FileFilter is a functional interface and can be assigned by Lambda expression
            FileFilter Abstract method boolean accept(File pathname) of interface

            Lambda Expression: (file pathname) - > {filter conditions for files or directories}
            Lambda Expression: (file pathname) - > {return pathname. Getname(). Endswith (". Exe");}

         */
//        File[] files = dir.listFiles((File pathname) -> { return pathname.getName().endsWith(".exe");});

        //(2) When {Lambda body} has only one statement, you can omit {} and the following statement;. If this is a return statement, you should also omit return
//        File[] files = dir.listFiles((File pathname) ->pathname.getName().endsWith(".exe"));

        //(3) When the parameter type of the parameter list (parameter list of Lambda expression) is known or can be inferred automatically according to the generic type, the type can be omitted
//        File[] files = dir.listFiles((pathname) ->pathname.getName().endsWith(".exe"));

        //(4) If the type of the formal parameter list of (the formal parameter list of Lambda expression) is omitted and there is only one formal parameter, then () can be omitted,
        File[] files = dir.listFiles(pathname ->pathname.getName().endsWith(".exe"));

        for (File file : files) {
            System.out.println(file);
        }
    }

    @Test
    public void test03(){
        //Requirements: List "D: \ to"_ Student \ Shang Silicon Valley_ 210728Java_ Chai Linyan_ . exe file in the directory "JavaSE \ pre installed software"
        File dir = new File("D:\\to_student\\Shang Silicon Valley_210728Java_Chai Linyan_JavaSE\\Pre installed software");

        File[] files = dir.listFiles(new FileFilter() {
            @Override
            public boolean accept(File pathname) {//The (File pathname) parameter is the next level file or directory object of the dir directory
                return pathname.getName().endsWith(".exe");
            }
        });
        for (File file : files) {
            System.out.println(file);
        }
    }

    @Test
    public void test02(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};
        //You want to sort this array, case insensitive
        //Public static < T > void sort (t [] A, comparator <? super T> c)
        //T[] a: receive an object array and transfer it to which array to sort
        //Comparator<?  Super T > C: requires an implementation class object of the comparator interface
        /*
        The implementation class object of the Comparator interface is not passed here. We assign a value to it with a Lambda expression.
            Comparator Abstract method int compare of interface (t T1, t T2)
         Lambda expression:
            (T t1, T t2) -> {Write the collation}

           T What is the type? Because the implementation class object of the Comparator interface, or int compare(T t1, T t2) sorts the elements of the arr array,
                        The array is of String [] type, the element is of String type, and the T is of String type

         Lambda expression:
            (String t1, String t2) -> {Write t1,t2 collation, case sensitive sorting}
            (String t1, String t2) -> {t1.compareToIgnoreCase(t2);}

         Because int compare(T t1, T t2) has a return value type of int, a return statement is required in {}

         Lambda expression:
            (String t1, String t2) -> {return t1.compareToIgnoreCase(t2);}
         */
//        Arrays.sort(arr, (String t1, String t2) -> {return t1.compareToIgnoreCase(t2);});

        //(2) When {Lambda body} has only one statement, you can omit {} and the following statement;. If this is a return statement, you should also omit return
//        Arrays.sort(arr, (String t1, String t2) -> t1.compareToIgnoreCase(t2));

        //(3) When the parameter type of the parameter list (parameter list of Lambda expression) is known or can be inferred automatically according to the generic type, the type can be omitted
        Arrays.sort(arr, (t1, t2) -> t1.compareToIgnoreCase(t2));
    }

    @Test
    public void test01(){
        //Requirements: start a thread by implementing the Runnable interface and print "hello"“
        //Thread(Runnable target). The constructor needs an implementation class object of Runnable interface. Now it needs to pass Lambda expression
        /*
        Assign a value to the (Runnable target) parameter using a Lambda expression.
        java.lang.Runnable Abstract method of interface void run()

        Lambda expression:
            () -> {System.out.println("hell");}
         */
//        new Thread(() -> {System.out.println("hello");}).start();

        //When {Lambda body} has only one statement, you can omit {} and the following statement;
        new Thread(() -> System.out.println("hello")).start();
    }
}

4. Demonstrate the application of Lambda expression of functional interface added in Java 8
(1) Consumer interface
    Consumer<T>  void accept(T t)

  Java 8 not only adds functional interfaces, but also upgrades the API of the collection framework.
  A default method is added to the Java. Lang. Iterable < T > interface in Java version 8:
    default void forEach(Consumer<? Super T > action): this method is used to traverse / iterate over the elements in the container

  Observe that the formal parameter list of this method is   ( Consumer<? Super T > action), the type of parameter consumer is a functional interface,
  So when you call this method, you can pass in a Lambda expression.

  Because the Collection of the Collection series inherits / implements the iteratable < T > interface, the Collection of the Collection series has a forEach method.

 ( 2) Consumer interface
  Biconsumer < T, u > abstract method   void accept(T t, U u)

  Java8 is also added in the Java. Util. Map < K, V > interface
    default void forEach(BiConsumer<? super K,? super V> action)

  The formal parameter of the forEach method: BiConsumer, which is also a functional interface, a deformation of the Consumer, and a Consumer interface

 ( 3) Judgment interface
  Predicate < T > abstract method   boolean test(T t)

  In the Java 8 version, the method default Boolean removeif (predict <?) is added to the Collection interface? super E> filter)
  The formal parameter type of this method: Predicate, which is a functional interface and a judgment functional interface

 ( 4) Functional interface
BiFunction<T,U,R>   Abstract method   R apply(T t, U u)


  In JDK1.8, add methods to Map interface:
    default void replaceAll(BiFunction<? super K,? super V,? extends V> function)

  The formal parameter of the replaceAll method is   BiFunction, which is a functional interface

public class TestLambda2 {
    @Test
    public void test05(){
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"java");

        //Requirement: replace the string containing o letter in the string of value with uppercase
        //Call default void replaceall (bifunction <? super K,?  super V,?  extends V> function)
        /*
        replaceAll The formal parameter of the method is BiFunction, which is a functional interface, and the abstract method r apply (T, u, U)
        Lambda expression:
            T: Is the key type of map
            U: Is the value type of map
            (Integer key, String value) -> {Replace the string containing o letter in the string of value with uppercase}
            (Integer key, String value) -> {
                        if(value.contains("o")){
                            return value.toUpperCase();//Returns the capitalized value
                        }
                        return value;//Return the original value
            }
         */
        map.replaceAll((Integer key, String value) -> {
            if(value.contains("o")){
                return value.toUpperCase();//Returns the capitalized value
            }
            return value;//Return the original value
        });

        //simplify:
        map.replaceAll((key, value) -> value.contains("o") ? value.toUpperCase() : value);

        System.out.println(map);
    }
    @Test
    public void test04(){
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "hello","java","world","mysql");

        //If required, delete the string containing o letter in the string
       //Call default Boolean removeif (predict <? super E> filter)
        /*
        The formal parameter is Predicate, which is a functional interface, a judgment functional interface, and an abstract method Boolean test (T)
                To call this method, you need to pass a parameter. After this parameter is passed in, the test method must be used for condition judgment. If the xx condition is met, it returns true, otherwise it returns false.
        Lambda Expression: (t) - > {judge whether t meets the deletion condition}
            T Type is the type of collection element, String type
        Lambda Expression: (string t) - > {return t.contains ("O");}
        */
//        list.removeIf((String t)->{ return t.contains("o");});

        //simplify
//        list.removeIf(t->t.contains("o"));

        list.removeIf(element->element.contains("o")); //Modify the formal parameter name to make it more readable

        System.out.println(list);
    }

    @Test
    public void test03(){
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "hello","java","world","mysql");

        //If required, delete the string containing o letter in the string
        //To delete a Collection of the original Collection series according to conditions, you must use the Iterator iterator
        Iterator<String> iterator = list.iterator();
        while(iterator.hasNext()){
            String str = iterator.next();
            if(str.contains("o")){
                iterator.remove();
            }
        }
    }

    @Test
    public void test02(){
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"java");

        //Call map's default void foreach (biconsumer <?)? super K,?  super V> action)
        /*
        Formal parameter BiConsumer, which is also a functional interface, and its abstract method void accept (T, u, U)
        Lambda Expression: (T, u, U) this T and u are actually K and V of Map
            (Integer key, String value) -> {Traverse key value pair}
         */
//        map.forEach((Integer key, String value) -> {System.out.println(key+":" + value);});

        //simplify
        map.forEach((key, value) -> System.out.println(key+":" + value));
    }

    @Test
    public void test01(){
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list, "hello","java","world","mysql");

        //Call default void foreach (consumer <?)? Super T > action) method
        /*
        The formal parameters are: Consumer type, which is a functional interface, and its abstract method void accept (T)
        lambda expression:
            (T t) -> {Traverse the elements of the collection}
         T The type of is determined by the element type of the collection. It is a String type
          lambda expression:
            (String t) -> {System.out.println(t);}
         */
//        list.forEach((String t) -> {System.out.println(t);} );

        //simplify
        list.forEach(t -> System.out.println(t));
    }
}

4, Method references and constructor references
1. Lambda expression is a syntax used to assign values to variables / formal parameters of "functional interface (SAM interface, interface with only one abstract method)".
It can simplify / replace the original anonymous inner class to implement the code of functional interface.

Method reference is another simplification of Lambda expression.

2. Syntax format of method reference and constructor reference:
  Method reference:   Class name / object name:: method name
  Constructor reference: Class Name:: new

3. Explain
(1) When there is only one statement in {lambda body}, and this statement is completed by calling the methods of existing objects / classes.
(2) The formal parameters in the (formal parameter list) of a Lambda expression are either used as the object of the calling method or as the arguments of the calling method. All formal parameters are used
(3) In the whole {lambda body}, no additional data / objects are used

For example: arrays. Sort (arr, (T1, T2) - > T1. Comparetoignorecase (T2));
(1) There is only one statement in the {lambda body}     return t1.compareToIgnoreCase(t2);
(2) The (formal parameter list) of the Lambda expression is (t1, t2), and t1 is the object that calls the compareToIgnoreCase method,
                                      t2 is the argument to call the compareToIgnoreCase method.

For example: list. Foreach (T - > system. Out. Println (T));
(1) There is only one statement in the {lambda body}     System.out.println(t)
(2) The (formal parameter list) of the Lambda expression is (string t), which is used as the argument of the println method call.

For example: new thread (() - > system. Out. Println ("hello")). Start();
(1) There is only one statement in the {lambda body}   System.out.println("hello")
(2) The (formal parameter list) of Lambda expression is (), and no parameters can be used
(3) In the whole {lambda body}, no additional data / objects are used   Not satisfied because "hello" appeared

public class TestFunction {

    @Test
    public void test04(){
        //Supply interface supplier < T >, abstract method T get()
        //Lambda expressions can directly assign values to variables of functional interfaces
//        Supplier<String> s = () -> new String();

        //Simplify with constructor references
        Supplier<String> s = String :: new;
    }

    @Test
    public void test03(){
        //Requirements: start a thread by implementing the Runnable interface and print "hello"“
        new Thread(()->System.out.println("hello")).start();//Multithreading prints a "hello"

        //Can method references be used for simplification? Cannot simplify
        new Thread(System.out::println).start(); //Multithreading just prints an empty line
    }
    @Test
    public void test02(){
        //Collection traversal
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"hello","java","world");

        //Call the forEach method for traversal
        //The formal parameter type of forEach is consumer < T >, and the abstract method void accept (T)
//        list.forEach(t -> System.out.println(t));

        //Simplify with method references
        list.forEach(System.out::println);
    }

    @Test
    public void test01(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};

        //Realize sorting, case insensitive sorting
//        Arrays.sort(arr, (t1, t2) -> t1.compareToIgnoreCase(t2));

        //Use method references for simplification
        Arrays.sort(arr, String::compareToIgnoreCase);

        System.out.println(Arrays.toString(arr));
    }
}

4. Many functional interfaces have been added to JDK 1.8. They are in the java.util.function package.
Four representatives:
(1) Consumer < T >, consumer interface         Abstract method: void accept (T)              

Features: with parameters and no return value       To call this method, you need to pass an argument to it, but you can't get the return value, "there is no return"
(2) Supplier < T >, supply type interface       Abstract method: T get()                    

    Features: no parameter with return value       The caller method does not need to pass parameters, but can get a return value, "empty handed White Wolf"         The abstract method of this interface is equivalent to "dedication"
 ( 3) Predicate < T >, judgment interface       Abstract method: Boolean test (T)      

        Features: there are parameters and return values, but the return value type is boolean
                  To call this method, you need to pass a parameter. After this parameter is passed in, the test method must be used for condition judgment. If the xx condition is met, it returns true, otherwise it returns false.
(4) Function < T, R >: functional interface       Abstract method: R apply (T)          

    Features: there are parameters and return values. The types of parameters and return values are uncertain and may be different
             When calling this method, you need to pass parameters and get a return value. However, the type of parameters and the type of return value can only be determined when using. Anything is possible. So this method is equivalent to just completing a function.

Other interfaces are all deformations of the above interfaces:
(1) Consumer < T >, consumer interface

bi: binary binary

(2) Supplier < T >, supply type interface

 

(3) (3) predict < T >, judgment interface, judgment interface  

(4) Function < T, R >: functional interface

 

  UnaryOperator: unary, one parameter and one return value. The parameter type is the same as the return value type
  BinaryOperator = Bi + UnaryOperator. There are two parameters, one return value. The types of parameters and return values are the same

  5. Custom functional interface
(1) This interface can only define one abstract method
(2) This interface is annotated with @ functional interface

public class TestFunctionalInterface3 {
}

@FunctionalInterface
interface MyInterface{
    void method();
}

//There is no need to define the following interface, because there are similar types under the java.util.function package of java8
//|Intconsumer | void accept (int value) | receives an int value
@FunctionalInterface
interface OtherInterface{
    void method(int a);
}

5, Java 8 adds a new tool class / container: Java. Util. Optional < T >
1. The object of the Optional class is a container, which is used to hold objects
Maybe it's empty, maybe there's an object in it,
This class is usually used as the return value of a method to avoid returning null values.

By far, the notorious null pointer exception is the most common cause of failure in Java applications.
Previously, in order to solve the null pointer exception, Google's famous Guava project introduced the Optional class,
Guava prevents code pollution by checking null values, which encourages programmers to write cleaner code.
Inspired by Google Guava, the Optional class has become part of the Java 8 class library.

For example, the return value of some methods in the Stream API is the Optional class.
| **Optional<T>** **findFirst()**            | Returns the first element                                               |
| **Optional<T>** **findAny()**              | Returns any element in the current stream                                       |                                       |
| **Optional<T>** **max(Comparator c)**      | Returns the maximum value in the stream                                               |
| **Optional<T>** **min(Comparator c)**     | Returns the minimum value in the stream
Because there may be no elements in the stream, these methods do not return real elements. If there is no option, they need to return null,
Null pointer exceptions may occur where these methods are called.

2. How to create an object of Optional class
(1) Create an empty container object       Optional.empty();
(2) Create a container object, which may contain null values or specific values   Optional.ofNullable(x);   X may be empty
(3) Create a non empty container object,   Optional.of(x);   X must be non empty

3. If flowers use Optional
(1) Judge whether it is empty
boolean isPresent()

(2) Get the object inside
T get()  : Take out the object in the Optional container. There must be an object in it, otherwise NoSuchElementException will be thrown
T orElse(T other)  : If there are objects in the Optional container, the objects in it will be returned directly; otherwise, the spare tire will be returned
T orElseGet(Supplier<? extends T> other)  : If there are objects in the Optional container, the objects in it will be returned directly. Otherwise, the spare tire provided by the supplier supplied interface will be returned

(3)void ifPresent(Consumer<? super T> consumer)

public class TestOptional {
    @Test
    public void test01(){
        Optional<Object> empty = Optional.empty();
        System.out.println(empty);
    }

    @Test
    public void test03(){
        Optional<String> opt = findGirlFriend2("Wang Fei");
        System.out.println(opt);
        System.out.println("Does Wang Fei's girlfriend exist " + opt.isPresent());
        System.out.println("girl friend:" + opt.get());
        opt.ifPresent(System.out::println);//If your girlfriend exists, print it, otherwise don't print it

        Optional<String> opt2 = findGirlFriend2("Li tianqi");
        System.out.println("opt2 = " + opt2);// Optional.empty
        System.out.println("Does Li Tianqi's female friend exist " + opt2.isPresent());
//        System.out.println("girlfriend:" + opt2.get());
        System.out.println("girl friend:" + opt2.orElse("Pomegranate sister"));
        System.out.println("girl friend:" + opt2.orElseGet(String::new));//Empty string
        opt2.ifPresent(System.out::println);//If your girlfriend exists, print it, otherwise don't print it

    }

    public Optional<String> findGirlFriend2(String boyName){
        HashMap<String,String > map = new HashMap<>();//This collection is followed by the data in the database
        map.put("Wang Fei", "Like flowers");
        map.put("careless", "Cuihua");
        map.put("Qiu Shiyu", "Jade like");
        map.put("Li tianqi", null);

        return Optional.ofNullable(map.get(boyName));
    }

    @Test
    public void test02(){
        String girl1 = findGirlFriend("Wang Fei");
        System.out.println("girl1 = " + girl1);
        System.out.println("Last name:" + girl1.charAt(0));

        String girl2 = findGirlFriend("Li tianqi");
        System.out.println("girl2 = " + girl2);
        System.out.println("Last name:" + girl2.charAt(0));
    }
    public String findGirlFriend(String boyName){
        HashMap<String,String > map = new HashMap<>();//This collection is followed by the data in the database
        map.put("Wang Fei", "Like flowers");
        map.put("careless", "Cuihua");
        map.put("Qiu Shiyu", "Jade like");
        map.put("Li tianqi", null);

        return map.get(boyName);
    }
}

6, StreamAPI
1. Stream: stream
We learned in the IO chapter before   InputStream and OutputStream are different from the Stream we are going to learn today. It doesn't matter.

2. Java 8 new package, java.util.stream
Function: to operate data in containers such as collections.
Using the Stream API to operate on the collection data is similar to a database query executed using SQL. You can also use the Stream API to perform operations in parallel.

Database: a simple understanding of data warehouse, used to store data.
      Database is a management system, which can be used to store data and manage data (addition, deletion, modification, query, backup...)
The database is divided into:
    Database of file system (data stored on hard disk)
    In memory database (data stored in memory)

    The advantage of being on the hard disk: permanent storage. Even if the system is powered off, the data will not be lost
    Advantages of in memory database: high speed

3. The use of Stream API is divided into three steps:
Step 1: create a Stream
Tell the Stream what the data source is

Step 2: intermediate operation to process data

Step 3: end the operation and see the final result


4. Characteristics of Stream API
(1) The Stream object is immutable. Any modification will produce a new Stream object, which must be received again
(2) The operation of Stream stream will not change the original data
(3) The intermediate operation can be 0~n steps
(4) The intermediate operation is a delay operation. The intermediate operation will not be executed until we want to execute the termination operation and execute it at one go
(5) Once terminated, it ends unless a new Stream is created
(6) Stream is not responsible for storing data, but only for processing data

public class TestStream {
    @Test
    public void test2() {
        ArrayList<Student> list = new ArrayList<>();
        list.add(new Student("Zhang San",89));
        list.add(new Student("Li Si",45));
        list.add(new Student("Wang Wu",75));

        //Step 1: create a Stream
        Stream<Student> stream = list.stream();

        //Step 2: intermediate operation to process data
        stream = stream.filter(s -> s.getScore()<60);//Find out if you fail

        //        Step 3: end the operation and see the final result
        stream.forEach(System.out::println);

    }
    @Test
    public void test(){
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"hello","world","java","hao");

        //Step 1: create a Stream
        Stream<String> stream = list.stream();

        //Step 2: intermediate operation to process data
        stream = stream.filter(t -> t.contains("o"));//Only words containing the letter "o" are left
        stream = stream.sorted();

//        Step 3: end the operation and see the final result
        stream.forEach(System.out::println);

        System.out.println(list);
    }
}

class Student{
    private String name;
    private int score;

    public Student(String name, int score) {
        this.name = name;
        this.score = score;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getScore() {
        System.out.println("getScore Method was called");
        return score;
    }

    public void setScore(int score) {
        this.score = score;
    }

    @Override
    public String toString() {
        return "Student{" +
                "name='" + name + '\'' +
                ", score=" + score +
                '}';
    }
}

5. How to create a Stream
(1) Collection. stream()
For the Collection of Collection series, a method is added after Java 8: default stream < E > stream ()

The Collection of Map series should be converted to the Collection series before obtaining the Stream.

(2) Arrays.stream (array)
A batch of streams are added to the array tool class Arrays, which can be created according to the array

(3) The static method of the Stream interface, the of method, creates a limited Stream
Stream.of(T... args)
Stream.of(T t)

(4) The static methods of the Stream interface, generate and iterate, create an infinite Stream
static <T> Stream<T> generate(Supplier<T> s)
static <T> Stream<T> iterate(T seed,  UnaryOperator<T> f)

public class TestCreateStream {
    @Test
    public void test11(){
        /*
        static <T> Stream<T> iterate(T seed,  UnaryOperator<T> f)
        iterate Method has two formal parameters:
        The first is T seed, seed
        The second is unaryoperator < T >, which is one of the functional interfaces learned today,
                UnaryOperator<T>The abstract method T apply(T t) has parameters and return values. The types of parameters and return values are the same

          Demand: start from seed (number 1) and accumulate 2 continuously
         */
        //Step 1: create a Stream
        Stream<Integer> stream = Stream.iterate(1, t -> t + 2);

        //Step 3: terminate the operation
        stream.forEach(System.out::println);
    }
    @Test
    public void test10(){
        /*
        static <T> Stream<T> generate(Supplier<T> s)
        generate The formal parameter type of the method is supplier < T >, which is a supply functional interface. The abstract method is T get()
        Lambda Expressions can assign values to (supplier < T > s) formal parameters
          Lambda expression:
                () -> {There is a statement that can generate data}


         */
        //Step 1: create a Stream
//        Stream<Double> stream = Stream.generate(() -> {return Math.random();});

//        Stream<Double> stream = Stream.generate(() -> Math.random());

        //Use method reference simplification
        Stream<Double> stream = Stream.generate(Math::random);

        //Step 3: terminate the operation
        stream.forEach(System.out::println);
    }

    @Test
    public void test9(){
        Stream<String> stream = Stream.of("hello", "java", "world");
    }
    @Test
    public void test8(){
        Integer[] arr = {1,2,3,4};
        Stream<Integer> stream = Arrays.stream(arr);

    }

    @Test
    public void test4(){
        int[] arr = {1,2,3,4};
        IntStream stream = Arrays.stream(arr);

    }

    @Test
    public void test3(){
        String[] arr = {"hello","java","world"};

        Stream<String> stream = Arrays.stream(arr);
    }
    @Test
    public void test2(){
        HashMap<Integer,String> map = new HashMap<>();
        map.put(1,"hello");
        map.put(2,"world");
        map.put(3,"java");

        Set<Integer> keys = map.keySet();
        Stream<Integer> keyStream = keys.stream();

        System.out.println("-------------------------");
        Collection<String> values = map.values();
        Stream<String> valueStream = values.stream();

        System.out.println("-------------------------");
        Set<Map.Entry<Integer, String>> entries = map.entrySet();
        Stream<Map.Entry<Integer, String>> entryStream = entries.stream();
    }

    @Test
    public void test(){
        ArrayList<String> list = new ArrayList<>();
        Collections.addAll(list,"hello","world","java","hao");

        Stream<String> stream = list.stream();
    }
}

6. Intermediate operation of Stream: the return value type of these methods is Stream

(1) filter filtering
(2) distinct() de duplication
(3) limit(long maxSize) limit the number of
(4) skip(long n) skip the previous few
(5) sorted(): using the natural sorting of elements, elements are required to implement the Comparable interface
    sorted(Comparator com), which uses custom sorting to specify Comparator comparison rules

(6) peek(Consumer action): the element in the stream performs the operation specified in the action, but does not modify the element
  ( 7)map(Function f): xxx operation is mapped to each element in the stream
(8) flatMap(Function f): synthesize the result of the small Stream obtained from the method body in the f functional interface into a large Stream

public class TestMiddleStream {

    @Test
    public void test14(){
        String[] arr = {"hello","world","java"};
        //Step 1: create a Stream
        Stream<String> stream = Arrays.stream(arr);

        //Step 2: intermediate processing, break each word in the above stream into letters one by one
        //t.split("|"): split the String to get a String [] array one by one. The element is a single letter
        //Stream.of(t.split("|): build the array into a small stream
        //map: take the Stream.of(t.split("|") to get the Stream as the element of the new Stream
        Stream<Stream<String>> streamStream = stream.map(t -> Stream.of(t.split("|")));
        //Step 3: terminate the operation
        streamStream.forEach(System.out::println);
    }

    @Test
    public void test13(){
        String str = "hello";
        String[] strings = str.split("|");
        System.out.println(Arrays.toString(strings));//[h, e, l, l, o]
    }
    @Test
    public void test12(){
        String[] arr = {"hello","world","java"};
        //Step 1: create a Stream
        Stream<String> stream = Arrays.stream(arr);
        
        //Step 2: intermediate processing, break each word in the above stream into letters one by one
        //t.split("|"): split the String to get a String [] array one by one. The element is a single letter
        //Stream.of(t.split("|): build the array into a small stream
        //flatMap: merge the streams obtained from Stream.of(t.split("|") into one large Stream
        Stream<String> stringStream = stream.flatMap(t -> Stream.of(t.split("|")));
        //Step 3: terminate the operation
        stringStream.forEach(System.out::println);
    }

    @Test
    public void test10(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};

        //Take the first letter of each string
        /*
        map(Function f)The formal parameter of the method is function < T, R > functional interface, and the abstract method is r apply (T)
         */
        Arrays.stream(arr).map(t-> t.charAt(0)).forEach(System.out::println);

  /*      //Step 1: create a Stream
        Stream<String> stream = Arrays.stream(arr);

        //Step 2: intermediate processing
        Stream<Character> characterStream = stream.map(t -> t.charAt(0));

        //Step 3: end
        characterStream.forEach(System.out::println);*/
    }

    @Test
    public void test09(){
        //Randomly generate 10 [0100) integers, and then take out the top three largest numbers
        List<Integer> collect = Stream.generate(() -> (int) (Math.random() * 100))
                .limit(10)
                .peek(System.out::println)
                .sorted((t1,t2)-> t2-t1)
                .limit(3)
                .collect(Collectors.toList());
        System.out.println(collect);
    }

    @Test
    public void test08(){
        //Randomly generate 10 [0100) integers, and then take out the top three largest numbers
        List<Integer> collect = Stream.generate(() -> (int) (Math.random() * 100))
                .limit(10)
                .peek(System.out::println)
                .sorted()
                .skip(7)
                .collect(Collectors.toList());
        System.out.println(collect);
    }

    @Test
    public void test07(){
        //Randomly generate 10 [0100) integers, and then take out the top three largest numbers
        Stream.generate(() -> (int)(Math.random()*100)).limit(10).sorted().skip(7).forEach(System.out::println);
    }
    @Test
    public void test06(){
        //There is an array of strings
        String[] arr = {"hello","Hi","Chai","Jock","world","atguigu"};

        //Sort by string size, case insensitive
        //Scheme 1: Arrays.sort
        //Scheme 2: use Stream
        Arrays.stream(arr).sorted(String::compareToIgnoreCase).forEach(System.out::println);
    }

    @Test
    public void test05() {
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8);

        //Skip the first three and take another three
        list.stream().skip(3).limit(3).forEach(System.out::println);
    }

        @Test
    public void test04(){
        //Use the Math.random() method to randomly generate some data, and take the first 10
        Stream.generate(Math::random).limit(10).forEach(System.out::println);
    }


    @Test
    public void test03(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5,6,7,8,1,2,3,4,5,6,7,8);

        //Get the non duplicate elements in the collection, that is, remove the duplicate elements
        //Scheme 1: it can be put into set
        //Scheme 2: Stream can be used
        //Three steps together
        list.stream().distinct().forEach(System.out::println);
    }


    @Test
    public void test02(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5,6,7,8);

        //Gets all even numbers in the list collection
        //Three steps together
        list.stream().filter(t -> t % 2 == 0).forEach(System.out::println);
    }

    @Test
    public void test01(){
        ArrayList<Integer> list = new ArrayList<>();
        Collections.addAll(list,1,2,3,4,5,6,7,8);

        //Gets all even numbers in the list collection
        //Step 1: create a Stream
        Stream<Integer> stream = list.stream();

        //Step 2: filter and leave the even number
        /*
        filter(Predicate p)The formal parameters of the method are the judgment interface predict < T >, and the abstract method Boolean test (T)
         */
        stream = stream.filter(t -> t % 2 == 0);

        //Step 3: end the operation and print the result
        stream.forEach(System.out::println);
    }
}

7. Stream termination operation: when we call a method of stream and the return value type of this method is not stream type, it means that this operation is a termination operation

 

(1) allMatch: judge whether the elements in the flow match xx conditions
(2) anyMatch: any match
(3) noneMatch: none of them match the xx condition
(4) findFirst: returns the first
      findAny: returns any     If the data of this stream is fixed, then findAny and findFirst
                            If the stream is an infinite stream or the elements in the stream are not fixed, the result of findAny is different from findFirst

 (5)long  count()
 (6)Optional<T> max(Comparator c)
    Optional<T> min(Comparator c)
 (7)void forEach(Consumer c)
 (8)T reduce(T iden, BinaryOperator b)
          U reduce(BinaryOperator b)
(9)R   collect(Collector c): collect the remaining elements in the stream into a collection or other container
        This method needs to work with the Collectors tool class

public class TestEndStream {
    @Test
    public void test11() {
        //Randomly generate 10 integers between [0,10], print 10 integers, and collect even numbers, which cannot be repeated
        List<Integer> list = Stream.generate(() -> (int) (Math.random() * 10))
                .limit(10)
                .peek(System.out::println)
                .filter(t->t%2==0)
                .distinct()
                .collect(Collectors.toList());
        System.out.println("list = " + list);
    }
    @Test
    public void test10() {
        //Randomly generate 10 integers between [0,10], print 10 integers, and collect even numbers, which cannot be repeated
        Set<Integer> set = Stream.generate(() -> (int) (Math.random() * 10))
                .limit(10)
                .peek(System.out::println)
                .filter(t -> t % 2 == 0)
                .collect(Collectors.toSet());
        System.out.println("set = " + set);
    }

    @Test
    public void test09() {
        //Randomly generate 10 integers between [0,10], print 10 integers, and collect even numbers
        List<Integer> list = Stream.generate(() -> (int) (Math.random() * 10))
                .limit(10)
                .peek(System.out::println)
                .filter(t->t%2==0)
                .collect(Collectors.toList());
        System.out.println("list = " + list);
    }
    @Test
    public void test08() {
        //Randomly generate 10 integers between [0,10], print 10 integers, and accumulate their sum
        Optional<Integer> result = Stream.generate(() -> (int) (Math.random() * 10))
                .limit(10)
                .peek(System.out::println)

                .reduce((t1, t2) -> t1 + t2);
        /*
        reduce(BinaryOperator b)The formal parameter binaryoperator < T > is a functional interface, and the abstract method t apply (T, t, U)
         */
        System.out.println("result = " + result);
    }
    @Test
    public void test07() {
        //Randomly generate 10 integers between [0100], print 10 integers, and return the maximum value
        Optional<Integer> max = Stream.generate(() -> (int) (Math.random() * 100))
                .limit(10)
                .peek(System.out::println)
                .max((t1, t2) -> t1 - t2);
        System.out.println("max = " + max);
    }
    @Test
    public void test06() {
        //Randomly generate 10 integers between [0100], print 10 integers, and count the even numbers inside
        ArrayList<Integer> list = new ArrayList<>();
        int count = 0;
        for(int i=0; i<10; i++){
            int num = (int) (Math.random() * 100);
            list.add(num);
            if(num%2==0){
                count++;
            }
        }
        System.out.println(list);
        System.out.println("Even number count = " + count);
    }
    @Test
    public void test05() {
        //Randomly generate 10 integers between [0100], print 10 integers, and count the even numbers inside
        long count = Stream.generate(() -> (int) (Math.random() * 100))
                .limit(10)
                .peek(System.out::println)
                .filter(t -> t % 2 == 0)
                .count();
        System.out.println("Even number count = " + count);
    }


    @Test
    public void test04() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        //Step 1: create a Stream
        Stream<Integer> stream = list.stream();

        //Step 2: leave an integer greater than 5
        stream = stream.filter(t -> t>5);

        //Step 3: findFirst
        Optional<Integer> first = stream.findFirst(); //Optional is a container that wraps the return value results
        System.out.println("first = " + first);//Optional.empty
    }

    @Test
    public void test03() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        //Step 1: create a Stream
        Stream<Integer> stream = list.stream();
        
        //Step 3: findFirst
        Optional<Integer> first = stream.findFirst(); //Optional is a container that wraps the return value results
        System.out.println("first = " + first);
    }
    @Test
    public void test02(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        //Step 1: create a Stream
        Stream<Integer> stream = list.stream();

        //Step 2: filter
        stream = stream.filter(t -> t % 2 == 0);//Only even numbers are left

        //Step 3: terminate the operation
        boolean result = stream.allMatch(t -> t % 2 == 0);
        System.out.println("result = " + result);
    }
    @Test
    public void test01(){
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        //Step 1: create a Stream
        Stream<Integer> stream = list.stream();

        //Step 3: terminate the operation
        boolean result = stream.allMatch(t -> t % 2 == 0);
        System.out.println("result = " + result);
    }
}

Tags: Java

Posted on Thu, 02 Sep 2021 19:31:19 -0400 by sanfly