Thread status, wait and wake up, Lambda expression, Stream flow

Chapter 1 thread status

1.1 thread status

The whole process of thread from life to death: technical literacy and interview requirements.

The process from creation to destruction of a thread is called the thread life cycle. There are six states in the thread life cycle:

Thread stateCondition causing the state to occur
New (New)The thread was just created but not started. The start method has not been called. MyThread t = new MyThread() has only thread objects and no thread characteristics. Error creating thread object
RunnableWhen the start() method is called, the thread may or may not be executing, depending on the scheduling of the operating system. When the start method is called
BlockedWhen a thread attempts to obtain a lock object and the lock object is held by another thread, the thread enters a lock blocking state; When the thread obtains the lock object, the thread will become runnable. Waiting for lock object
Waiting (unlimited waiting)When a thread is Waiting for another thread to perform a (wake-up) action, the thread enters the Waiting state. You cannot wake up automatically after entering this state. You must wait for another thread to call the notify or notifyAll method to wake up. When calling the wait() method
Timed waitingIn the same waiting state, several methods have timeout parameters. Calling them will enter the Timed Waiting state. This state will remain until the timeout period expires or a wake-up notification is received. A common method with timeout parameters is thread sleep ,Object.wait. An error occurred while calling the sleep() method
TerminatedDie because the run method exited normally, or because an uncapped exception terminated the run method. At the end of the run method execution

1.2 timed waiting and unlimited waiting

  • Timing and waiting: calling the sleep() method of the thread class can make the current thread enter the sleep state. When the sleep time reaches, the thread will wake up automatically.

    • public static void sleep(long time) enables the current thread to enter the sleep state and automatically wake up after milliseconds to continue execution

    • After the thread enters the timing wait state, the lock object and cpu are not released

      public class Test {
          public static void main(String[] args) throws InterruptedException {
              for (int i = 0; i < 100; i++) {
                  System.out.println("i Value of:"+i);
                  // Print once, pause for 3 seconds
                  Thread.sleep(3000);
              }
          }
      }
      
  • Infinite waiting

  • After the thread enters the infinite wait state, the lock object and cpu are released

    • Method of Object class:

      • public void wait(): let the current thread enter the waiting state. This method must be called by locking the object
  • public void notify(): wakes up the thread waiting on the current lock object. This method must be called on the lock object

    • public void notifyAll(): wakes up all waiting threads on the current lock object. This method must be called on the lock object

    • Case 1: infinite waiting thread

      public class Test1 {
          // Lock object
          public static Object obj = new Object();
      
          public static void main(String[] args) {
              // Create and start thread -- > Enter infinite wait
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("Infinite wait thread: Ready to enter infinite waiting...");
                      synchronized (obj) {
                          try {
                              obj.wait();// Enter infinite waiting
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("Infinite wait thread:Wake up by another thread,And get the lock object,Continue execution...");
                      }
                  }
              }).start();
          }
      }
      
    • Case 2: wait and wake up case

      public class Test2 {
          // Lock object
          public static Object obj = new Object();
      
          public static void main(String[] args) throws InterruptedException {
              // Create and start thread -- > Enter infinite wait
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("Infinite wait thread: Ready to enter infinite waiting...");
                      synchronized (obj) {// Lock
                          try {
                              obj.wait();// Enter infinite waiting
                          } catch (InterruptedException e) {
                              e.printStackTrace();
                          }
                          System.out.println("Infinite wait thread:Wake up by another thread,And get the lock object,Continue execution...");
                      }// Release lock
                  }
              }).start();
      
              // In order to let the infinite waiting thread execute first, sleep before starting the wake-up thread
              Thread.sleep(100);
      
              // Create and start thread -- > wake up waiting thread
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("Wake up thread:Prepare to wake up the infinite wait thread");
                      synchronized (obj){
                          obj.notify();
                      }
                  }
              }).start();
      
              /*
                  Analyzer:
                      1.When the program enters the infinite wait state, it will release the lock, release the cpu, and will not preempt again
                      2.The infinite wait thread is awakened. After getting the lock object, it will continue to execute from the position where it enters the infinite wait
               */
          }
      }
      

1.3 waiting for wake-up mechanism

  • Overview: use wait and wake to realize regular execution among multiple threads
  • For example, the sub thread prints the i loop and the main thread prints the j loop
  • Do not use the wake-up waiting mechanism: the result is that the main thread and sub thread randomly alternate printouts ----- > irregular
  • Use the wake-up waiting mechanism: the results should be printed out regularly
    • Print 1 i cycle, then print 1 j cycle... Cycle the print output in turn... --- > regular
    • How to achieve:
      • The sub thread prints an i-loop, then wakes up the main thread to execute, and enters an infinite wait
      • The main thread prints a j loop, then wakes up the sub thread to execute, and enters the infinite wait
      • The sub thread prints an i-loop, then wakes up the main thread to execute, and enters an infinite wait
      • The main thread prints a j loop, then wakes up the sub thread to execute, and enters the infinite wait
      • ...

How to implement the wake-up waiting mechanism:

  • 1. Use the lock object to call the wait() method to enter the infinite wait

  • 2. Use the lock object to call the notify() method to wake up the thread

  • 3. The lock objects calling the wait() and notify() methods should be consistent

  • Case: main thread and sub thread regularly alternate printouts

    public class MyThread extends Thread {
        @Override
        public void run() {
            for (int i = 0; i < 100; i++) {
                synchronized (Test.lock) {
                    if (Test.flag == false){
                        // Infinite waiting
                        try {
                            Test.lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
    
                    if (Test.flag == true) {
                        System.out.println("Child thread i The value of is:" + i);
                        Test.lock.notify();
                        Test.flag = false;
                    }
                }
            }
        }
    }
    
    public class Test {
        // Lock object
        public static Object lock = new Object();
        // Switch variable --- flag variable
        public static boolean flag = false;// true: child thread execution false: main thread execution
    
        public static void main(String[] args) {
            // Requirements: the main thread and sub thread regularly alternate printouts
            // Create and start a child thread
            new MyThread().start();
    
            // Tasks of the main thread
            for (int j = 0; j < 100; j++) {
                synchronized (lock) {
                    if (flag == true){
                        // Infinite waiting
                        try {
                            Test.lock.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
    
                    if (flag == false) {
                        System.out.println("Main thread j The value of is:" + j);
                        lock.notify();
                        flag = true;
                    }
                }
            }
            // result:
            // j-i-j-i-j-i-j....
        }
    }
    

Analyze the execution of the program waiting for wake-up mechanism

  • 1. Thread scheduling is preemptive regardless of whether the wake-up waiting mechanism is used
  • 2. When the thread enters the infinite wait, the thread will release the lock and the cpu will not compete again
  • 3. Wake up other threads. The current wake-up thread will not release the lock, and the cpu will not
  • 4. The infinite wait thread is awakened. After getting the lock object, it will continue to execute from the position where it enters the infinite wait

1.4 waiting for wake-up cases

demand

  • The waiting wake-up mechanism is actually a classic problem of "producers and consumers".

  • Take the production of steamed stuffed buns and the consumption of steamed stuffed buns as an example. How can the waiting wake-up mechanism make effective use of resources

analysis

Baozi shop thread production baozi,Finished production,There are steamed stuffed buns,Wake up the food thread to eat steamed stuffed buns,Then the Baozipu thread enters the infinite wait;
Eat steamed stuffed bun,I'm full,There are no steamed stuffed buns,Wake up the baozi shop thread to produce baozi,Then the eating thread enters an infinite wait;
Baozi shop thread production baozi,Finished production,There are steamed stuffed buns,Wake up the food thread to eat steamed stuffed buns,Then the Baozipu thread enters the infinite wait;
Eat steamed stuffed bun,I'm full,There are no steamed stuffed buns,Wake up the baozi shop thread to produce baozi,Then the eating thread enters an infinite wait;
.....
Steamed stuffed bun:
    state--->false:No steamed stuffed bun,ture:There are steamed stuffed buns
	filling
 Steamed stuffed bun shop thread:
	There are steamed stuffed buns,Enter infinite waiting
    The steamed stuffed bun is gone,Execute code(Production of steamed stuffed bun),Wake up other threads,Modify flag variable
 Eating thread:
    The steamed stuffed bun is gone,Enter infinite waiting
    There are steamed stuffed buns,Execute code(Eat steamed stuffed bun),Wake up other threads,Modify flag variable

realization

  • Steamed stuffed bun

    public class BaoZi {
        public String xian;
        public boolean flag;// The default value is false
    }
    
    
  • Steamed stuffed bun shop thread

    public class BaoZiPu extends Thread {
    
        BaoZi bz;
    
        public BaoZiPu(BaoZi bz) {
            this.bz = bz;
        }
    
        @Override
        public void run() {
            while (true) {
                synchronized (bz) {
                    // With the steamed stuffed bun, enter the infinite waiting
                    if (bz.flag == true){
                        try {
                            bz.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    // When the package is gone, execute the code (produce the package), wake up other threads, and modify the flag variable
                    if (bz.flag == false){
                        System.out.println("Steamed stuffed bun shop thread:Start making steamed stuffed buns...");
                        bz.xian = "filling for dumplings made with chives and pork";
                        bz.flag = true;
                        bz.notify();
                        System.out.println("Steamed stuffed bun shop thread:The steamed stuffed bun is ready,Food! Come and eat steamed stuffed buns...");
                    }
                }
            }
        }
    }
    
  • Eating thread

    public class ChiHuo extends Thread {
    
        BaoZi bz;
    
        public ChiHuo(BaoZi bz) {
            this.bz = bz;
        }
    
        @Override
        public void run() {
            while (true) {
                synchronized (bz) {
                    // The steamed stuffed bun is gone. Enter the infinite waiting
                    if (bz.flag == false){
                        try {
                            bz.wait();
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                    // When the package is available, execute the code (eat the package), wake up other threads, and modify the flag variable
                    if (bz.flag == true){
                        System.out.println("Eating thread:Start eating steamed stuffed buns,Stuffing of steamed stuffed bun:"+bz.xian);
                        bz.flag = false;
                        bz.notify();
                        System.out.println("Eating thread:The steamed stuffed bun is finished,Steamed stuffed bun shop, come and make steamed stuffed buns========");
                    }
                }
            }
        }
    }
    
  • Test class

    public class Test {
        public static void main(String[] args) {
            // Create package sub object
            BaoZi bz = new BaoZi();// xian: null,flag: false
    
            // Create and start the package sub store thread
            new BaoZiPu(bz).start();
    
            // Create and start the feed thread
            new ChiHuo(bz).start();
        }
    }
    

Chapter 2 Lambda expression

2.1 overview of functional programming ideas

Object oriented programming idea

Object oriented emphasizes that objects "must do things in the form of objects". It is relatively complex. Sometimes we have to create an object just to do something, such as thread execution task. We have to create an interface object that implements Runnable, but what we really want is to pass the code in the run method to the thread object for execution

Function programming idea

In mathematics, a function is a set of calculation schemes with input and output, that is, "what to do with". Relatively speaking, object-oriented overemphasizes that "things must be done in the form of objects", while functional thinking tries to ignore the complex object-oriented syntax - emphasizing what to do rather than what form to do. For example, when a thread executes a task, using the functional idea, we can pass a piece of code to the thread object for execution without creating a task object

2.2 Lambda expression experience

  • Create threads to execute tasks by implementing the Runnable interface

  • Anonymous inner class method to create threads to execute tasks

    • In fact, the above two methods pass tasks to threads for execution through Runnable implementation class objects
    • Thinking: can I pass tasks to threads for execution without implementing class objects? - > Functional programming
  • Creating threads to execute tasks in Lambda mode

    public class MyRunnable implements Runnable {
        @Override
        public void run() {
            System.out.println("Passing tasks by implementing classes");
        }
    }
    
    
    public class Test {
        public static void main(String[] args) {
            // Create threads to execute tasks by implementing the Runnable interface
            MyRunnable mr = new MyRunnable();
            new Thread(mr).start();
    
            //Anonymous inner class method to create threads to execute tasks
            new Thread(new Runnable() {
                @Override
                public void run() {
                    System.out.println("Passing tasks by anonymous inner classes");
                }
            }).start();
    
            //In fact, the above two methods pass tasks to threads for execution through Runnable implementation class objects
            // Thinking: can I pass tasks to threads for execution without implementing class objects? --- > Functional programming
            // Functional programming: emphasize what to do, not in what form
    
            //Creating threads to execute tasks in Lambda mode
            new Thread(()->{System.out.println("Transfer tasks in the way of thinking of functional programming");}).start();
        }
    }
    
  • Lambda expressions have no special functions and are used to simplify code

2.3 standard format of lambda expression

  • standard format

    • Format: (parameter type, parameter name, parameter type, parameter name,...) - > {code block}
  • Prerequisites for the use of Lambda:

    • Lambda expressions can only be used for interfaces with only one abstract method in the interface

    • The interface with only one abstract method is called a functional interface, which can be identified with the @ FunctionalInterface annotation

    • eg:

      // The A interface is A functional interface. You can replace the implementation class object with A Lambda expression
      public interface A{
          void method1();
      }
      // B interface is a functional interface. You can replace the implementation class object with Lambda expression
      @FunctionalInterface
      public interface B{
          void method1();
      }
      
      // C interface is not a functional interface, so Lambda expressions cannot be used
      public interface C{
          void method1();
          void method2();
      }
      
      // The D interface is a functional interface. You can replace the implementation class object with a Lambda expression
      public interface D{
          void method1();
          default void method2(){
              
          }
          ...
      }
      
  • Format description

    • The parameter type, number and order in parentheses shall be consistent with the formal parameter list of the abstract method in the functional interface
    • ->Fixed format, indicating pointing
    • The content in braces is actually the method body of the abstract method in the interface rewritten before
  • Case demonstration

    • Runnable functional interface

      public class Test {
          public static void main(String[] args) {
              // -Runnable functional interface
              new Thread(() -> {
                  System.out.println("Task code");
                  System.out.println("Task code");
                  System.out.println("Task code");
                  System.out.println("Task code");
              }).start();
          }
      }
      
  • Comparator functional interface

      public class Test {
          public static void main(String[] args) {
              // -Comparator functional interface
              ArrayList<Integer> list = new ArrayList<>();
              list.add(500);
              list.add(100);
              list.add(400);
              list.add(200);
              list.add(300);
              // Sort -- > ascending sort
              Collections.sort(list, (Integer i1, Integer i2) -> {
                  return i1 - i2;
              });
              System.out.println("Sorted collection:" + list);
      
              // Sort -- > descending sort
              Collections.sort(list,(Integer o1,Integer o2)->{
                  return o2 - o1;
              });
              System.out.println("Sorted collection:" + list);  
          }
      }
    
  • Lambda uses routine

    • 1. Judge whether Lambda expression can be used in this position - > use premise
    • 2. If it can be used, write () - > {}
    • 3. Fill in the contents in parentheses - > the formal parameters of abstract methods in functional interfaces are consistent
    • 4. Fill in the contents in braces - > rewrite the method body required by the functional interface abstract method

2.4 Lambda expression ellipsis format

  • Omission rule

    • Parameter types in parentheses can be omitted
    • If there is only one parameter in parentheses, parentheses and parameter types can be omitted together
    • If there is only one statement in braces, braces, return keyword and semicolon can also be omitted (the three should be omitted together)
  • Case demonstration

    public class Test {
        public static void main(String[] args) {
            // -Runnable functional interface
            // standard format 
            new Thread(() -> {
                System.out.println("Task code 1");
            }).start();
    
            // Omit format
            new Thread(() -> System.out.println("Task code 2")).start();
    
            // -Comparator functional interface
            ArrayList<Integer> list = new ArrayList<>();
            list.add(500);
            list.add(100);
            list.add(400);
            list.add(200);
            list.add(300);
            // Sort -- > ascending sort
            // Standard format:
            /*Collections.sort(list, (Integer i1, Integer i2) -> {
                return i1 - i2;
            });*/
    
            // Omit format:
            Collections.sort(list, ( i1,  i2) -> i1 - i2);
            System.out.println("Sorted collection:" + list);
    
            // Sort -- > descending sort
            // Omit format:
            Collections.sort(list,( o1, o2)-> o2 - o1);
            System.out.println("Sorted collection:" + list);
        }
    }
    

2.5 manifestations of lambda

  • Representation of Lambda: where will Lambda expressions appear

    • Variable form: assign a Lambda expression

      public class Test {
          public static void main(String[] args) {
              // -Variable form:
              Runnable r1 = new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("Runnable Anonymous Inner Class --Implementation class object");
                  }
              };
      
              Runnable r2 = () -> {
                  System.out.println("Runnable Corresponding Lambda expression");
              };  
          }
      }
      
  • Parameter form: pass in a Lambda expression as an argument

      public class Test {
          public static void main(String[] args) {
      
              Runnable r2 = () -> {
                  System.out.println("Runnable Corresponding Lambda expression");
              };
      
              // -Parameter form:
              new Thread(new Runnable() {
                  @Override
                  public void run() {
                      System.out.println("Runnable Anonymous Inner Class --Implementation class object");
                  }
              }).start();
      
              new Thread(() -> {
                  System.out.println("Runnable Corresponding Lambda expression");
              }).start();
              new Thread(r2).start(); 
          }
      }
    
    • Return value form: returns a Lambda expression (return value)

    public class Test {
    public static void main(String[] args) {
    //- return value form:
    //- Comparator functional interface
    ArrayList list = new ArrayList<>();
    list.add(500);
    list.add(100);
    list.add(400);
    list.add(200);
    list.add(300);
    Comparator comp = getComparator();
    Collections.sort(list, comp);
    System.out.println("after sorting:" + list);
    }

      public static Comparator<Integer> getComparator() {
          /*return new Comparator<Integer>() {
              @Override
              public int compare(Integer o1, Integer o2) {
                  return o2 - o1;
              }
          };*/
    
          //return (Integer o1, Integer o2)->{return o2 - o1;};//  standard format 
          return ( o1,  o2)-> o2 - o1;// Omit format
      }
    

    }

    
    
    
    
    

Chapter III Stream

In Java 8, thanks to the functional programming brought by Lambda, a new Stream concept is introduced to solve the existing disadvantages of the existing collection class library.

3.1 feel the Stream flow

  • Requirements:

     List<String> one = new ArrayList<>();
            one.add("Outlaw maniac");
            one.add("Song Yuanqiao");
            one.add("Su Xinghe");
            one.add("Laozi");
            one.add("Zhuangzi");
    		one.add("zhang wuji");
            one.add("grandson");
            one.add("master hongqi");
    demand:
    1. The names of the members of the team whose names are three words;
    2. After screening, only the first three people in the team;
    
  • Operation set

    public class Test {
        public static void main(String[] args) {
            List<String> one = new ArrayList<>();
            one.add("Outlaw maniac");
            one.add("Song Yuanqiao");
            one.add("Su Xinghe");
            one.add("Laozi");
            one.add("Zhuangzi");
            one.add("zhang wuji");
            one.add("grandson");
            one.add("master hongqi");
            // Requirements:
            // 1. The names of the members of the team whose names are three words;
            // 1.1 create a new set to store names with 3 words
            ArrayList<String> list1 = new ArrayList<>();
    
            // 1.2 loop through this set
            for (String name : one) {
                // 1.3 in the cycle, judge, filter and store
                if (name.length() == 3){
                    list1.add(name);
                }
            }
    
            // 2. After screening, only the first three people in the team;
            // 2.1 create a new set to store the first three
            ArrayList<String> list2 = new ArrayList<>();
    
            // 2.2 cycle through 3 times and store
            for (int i = 0; i < 3; i++) {
                String e = list1.get(i);
                list2.add(e);
            }
    
            System.out.println("list2:"+list2);
    
            // Stream stream: get stream -- > operation stream (filter) - > get result 
            one.stream().filter(name->name.length()==3).limit(3).forEach(name->System.out.println(name));
        }
    }
    

3.2 overview of streaming ideas

  • Overview: flow thinking can be compared to the assembly line \ River in the factory workshop

  • characteristic:

    • Flow must build a complete function model, and there must be a termination method in the function model

    • Stream stream cannot be operated repeatedly, that is, a stream stream can only be used once

    • Stream streams do not store data

    • Stream stream does not modify the data source

      Termination method: the return value type in stream is not stream

      Delay method: the return value type in stream is stream

3.3 access flow method

  • Get stream from collection - > collection there is a method to get stream in the collection public default stream < E > stream();

    • Get stream from Collection

      public class Test1_according to Collection Collection fetch stream {
          public static void main(String[] args) {
              // List
              List<String> list = new ArrayList<>();
              list.add("Zhang San");
              list.add("Li Si");
              list.add("Wang Wu");
              list.add("Zhao Liu");
              // Get stream
              Stream<String> stream1 = list.stream();
      
              // Set
              Set<String> set = new HashSet<>();
              set.add("Zhang San");
              set.add("Li Si");
              set.add("Wang Wu");
              set.add("Zhao Liu");
              // Get stream
              Stream<String> stream2 = set.stream();
          }
      }
      
    • Get stream from Map

      • Get the stream according to the key of the Map collection

      • Gets the stream based on the value of the Map collection

      • Get the flow of the object according to the key value of the Map collection

        public class Test2_according to Map Collection fetch stream {
            public static void main(String[] args) {
                Map<String,String> map = new HashMap<>();
                map.put("1","Zhang San");
                map.put("2","Li Si");
                map.put("3","Wang Wu");
                map.put("4","Zhao Liu");
                
                // -Get the stream according to the key of the Map collection
                Stream<String> stream1 = map.keySet().stream();
                
                //-Gets the stream based on the value of the Map collection
                Stream<String> stream2 = map.values().stream();
                
                //-Get the flow of the object according to the key value of the Map collection
                Stream<Map.Entry<String, String>> stream3 = map.entrySet().stream();
            }
        }
        
  • Get Stream according to array ----- > static of method using Stream stream Stream

    • public static <T> Stream<T> of(T... values);

      public class Test3_Get stream from array {
          public static void main(String[] args) {
              String[] arr = {"Zhang San","Li Si","Wang Wu","Zhao Liu"};
              // Get stream from array element
              Stream<String> stream1 = Stream.of(arr);
              
              // Direct value transfer acquisition stream
              Stream<String> stream2 = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu");
          }
      }
      

3.4 common methods of stream flow

  • Termination method: the return value type of the method is not a Stream. There must be a termination method in the Stream, otherwise it cannot be executed

  • Deferred method: the return value type of the method is Stream stream

  • Common methods:

    • forEach: process the elements in the stream one by one

      public class Test1_forEach {
          public static void main(String[] args) {
              /*
                  forEach:
                      void forEach(Consumer<? super T> action);Process the elements in the stream one by one
                      Parameter Consumer: functional interface
               */
              // Get stream
              Stream<String> stream = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu");
              // Requirements: output all elements in the flow separately
              //stream. forEach((String t)->{System.out.println(t);});//  standard format 
              stream.forEach(t -> System.out.println(t));// Omit format
          }
      }
      
    • count: counts the number of elements in the stream

    public class Test2_count {
    public static void main(String[] args) {
    /*
    forEach:
    long count(); Count the number of elements in the stream
    */

          // Get stream
          Stream<String> stream = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu");
          // Requirements: output all elements in the flow separately
          long count = stream.count();
          System.out.println("stream Number of stream elements:"+count);
      }
    

    }

    
    
  • Filter: filter by condition

      public class Test3_filter {
        public static void main(String[] args) {
              /*
                  filter:
                       Stream<T> filter(Predicate<? super T> predicate); Filter according to the specified conditions, and the elements that meet the conditions form a new Stream and return a new Stream stream
                       The parameter predict: functional interface ---- > is used for judgment
               */
              // Get stream
              Stream<String> stream = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu","Wang Qi");
              // Requirement: filter out the elements surnamed Wang and print out
              //stream. Filter ((string t) - > {return t.startswith ("King");}) forEach(e->System.out.println(e));
            stream.filter(t->t.startsWith("king")).forEach(e->System.out.println(e));
          }
      }
    
    • limit: get the first few elements in the stream
      public class Test4_limit {
        public static void main(String[] args) {
              /*
                limit:
                       Stream<T> limit(long maxSize); Take the first few elements
                      be careful: 
                          1.In general, the parameter is set to be greater than 0 and less than the number of elements in the flow
                          2.If the parameter setting is less than 0, an exception will be reported
                          3.If the parameter is set to 0, there are no elements in the returned stream
                          4.If the parameter setting is greater than the number of elements in the flow, the returned flow contains all the elements in the flow
               */
              // Get stream
              Stream<String> stream = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu","Wang Qi");
              // Requirement: take the first four elements and print out
              stream.limit(4).forEach(e-> System.out.println(e));
              //stream. limit(9). forEach(e-> System.out.println(e));//  Fetch all elements in the stream
              //stream. limit(-9). forEach(e-> System.out.println(e));//  IllegalArgumentException reported
          }
      }
    
    • Skip: skip the first few elements in the stream

    public class Test5_skip {
    public static void main(String[] args) {
    /*
    skip:
    Stream skip(long n); Skip the first few elements
    be careful:
    1. The parameter is generally set to be greater than 0 or less than the number of elements
    2. If the parameter is set to 0, the returned new stream contains all elements
    3. If the parameter is set to be greater than or equal to the number of elements, no elements in the new stream will be returned
    4. If the parameter is set to less than 0, an exception is reported
    */
    //Get stream
    Stream stream = Stream.of("Zhang San", "Li Si", "Wang Wu", "Zhao Liu", "Wang Qi");
    //Requirement: skip the first 4 elements and print out the remaining elements
    stream.skip(4).forEach(e-> System.out.println(e));
    //stream. skip(8). forEach(e-> System.out.println(e));// No element output
    //stream. skip(-8). forEach(e-> System.out.println(e));// Report exception
    }
    }

    
    
    - map: mapping\transformation
    
    ```java
    public class Test6_map {
      public static void main(String[] args) {
            /*
              map:
                    <R> Stream<R> map(Function<? super T, ? extends R> mapper); Convert elements of type T in the stream to elements of type R, and return a new stream (R)
                  be careful:
                        1.T,R The types of can be consistent or inconsistent
                        2.Parameter Function: functional interface -- > conversion interface
             */
            // Get stream
            Stream<String> stream = Stream.of("100", "200", "300", "400", "500");
            // Requirements: convert the string type in the stream to Integer type and print out
            stream.map((String t)->{return Integer.parseInt(t);}).forEach(e-> System.out.println(e+100));
        }
    }
    
    • concat: splice 2 streams

      public class Test7_concat {
          public static void main(String[] args) {
            /*
                  concat:
                    public static <T> Stream<T> concat(Stream<? extends T> a, Stream<? extends T> b) Splice the elements in the two streams to get a new stream
               */
            // Get stream
              Stream<String> stream1 = Stream.of("100", "200", "300", "400", "500");
              // Get stream
              Stream<String> stream2 = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu","Wang Qi");
              // Splicing
              Stream.concat(stream1,stream2).forEach(e-> System.out.println(e));
          }
      }
      

3.5 Stream comprehensive case

demand

Now there are two ArrayList collections to store the names of multiple members in the team. It is required to use the Stream stream Stream. Carry out the following steps in sequence:

  1. The first team only needs the name of the member whose name is three words;
  2. After the first team screening, only the first three people;
  3. The second team only needs the names of members surnamed Zhang;
  4. After the second team is screened, do not use the first two people;
  5. Merge the two teams into one team;
  6. Create a Person object based on the name;
  7. Print the Person object information of the whole team.

realization

public class Test {
    public static void main(String[] args) {
        List<String> one = new ArrayList<>();
        one.add("Outlaw maniac");
        one.add("Song Yuanqiao");
        one.add("Su Xinghe");
        one.add("Laozi");
        one.add("Zhuangzi");
        one.add("grandson");
        one.add("master hongqi");

        List<String> two = new ArrayList<>();
        two.add("Demacia");
        two.add("zhang wuji");
        two.add("Zhang Sanfeng");
        two.add("Zhao Wuji");
        two.add("Zhang Ergou");
        two.add("Zhang Zhang");
        two.add("Zhang San");

        // 1. The first team only needs the names of the members whose names are three words;
        // 2. After the screening of the first team, only the first three people;
        Stream<String> stream1 = one.stream().filter((String t) -> {
            return t.length() == 3;
        }).limit(3);

        // 3. The second team only needs the names of members surnamed Zhang;
        // 4. After the second team is screened, do not use the first two people;
        Stream<String> stream2 = two.stream().filter((String t) -> {
            return t.startsWith("Zhang");
        }).skip(2);

        // 5. Merge the two teams into one team;
        // 6. Create a Person object according to the name;
        // 7. Print the Person object information of the whole team.
        Stream.concat(stream1,stream2).map((String name)->{ return new Person(name);}).forEach(p-> System.out.println(p));        
    }
}

3.6 collect Stream results

Collect into array

  • public statci Object[] toArray(); Collect the elements in the stream into an array

    public class Test1_Collect into array {
        public static void main(String[] args) {
            // Get stream
            Stream<String> stream = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu","Wang Qi");
            // Requirement: filter out the elements surnamed Wang and collect the results into the array
            Object[] arr = stream.filter(name -> name.startsWith("king")).toArray();
            for (Object o : arr) {
                System.out.println(o);
            }
        }
    }
    

Collect into collection

  • <R, A> R collect(Collector<? super T, A, R> collector); Collect the elements in the stream into a collection

    • R: The return value type, that is to say, the collection of types will be returned according to the type of R

    • The generic R in the parameter Collector determines the return value type of the method

    • How to get the Collector??? ----- > Tool class Collectors

      • public static <T> Collector<T, ?, List<T>> toList()
      • public static <T> Collector<T, ?, Set<T>> toSet()
      • eg; stream.collect(Collectors.toList()) collects the List collection
      • eg: ``stream.collect(Collectors.toSet()) collected Set`
      public class Test1_Collect into collection {
          public static void main(String[] args) {
              // Get stream
              Stream<String> stream = Stream.of("Zhang San","Li Si","Wang Wu","Zhao Liu","Wang Qi");
              // Requirement: filter out the elements surnamed Wang and collect the results into the collection
              //List<String> list = stream. Filter (name - > name. Startswith ("Wang")) collect(Collectors.toList());
              //System.out.println("list:" + list);
      
              Set<String> set = stream.filter(name -> name.startsWith("king")).collect(Collectors.toSet());
              System.out.println("set:" + set);
          }
      }
      

summary

	1.Mutual switching between thread 6 states----->Drawing
    2.Wait for wake-up mechanism--->How to implement the wake-up waiting mechanism,How to analyze the execution process of waiting for wake-up mechanism cases
        2.1 Regular printing i Cycle and j loop
        2.2 Case of eating steamed stuffed bun
    3.Lambda expression: 
		3.1 Dictation use Lambda Expression routines---->4 step
        3.2 Premise of dictation
        3.3 Dictation ellipsis rule
    4.Stream flow:
		Comprehensive case---->Collect the results into an array or collection
            
- Be able to name the six states of the thread
    newly build,Operable,Lock blocking,Infinite waiting,Timed waiting ,Terminated
            
- Be able to understand cases of waiting for wake-up
  How to implement the wake-up waiting mechanism:
    - 1.Call with lock object wait()Method enters infinite wait
    - 2.Call with lock object notify()Method wakes up the thread
    - 3.call wait(),notify()The lock objects of the method should be consistent
  Analyze the execution of the program waiting for wake-up mechanism
    - 1.Whether wake-up waiting mechanism is used or not,Thread scheduling is preemptive
    - 2.Thread enters infinite wait,The thread releases the lock,cpu,And won't compete again
    - 3.Wake up other threads,The current wake-up thread will not release the lock,cpu of
    - 4.Infinite wait for the thread to wake up,After you get the lock object,It will continue to execute from the position of entering infinite waiting
     
- Can grasp Lambda Standard and omitted forms of expressions
   Lambda Use routine
    - 1.Judge whether it can be used in this position Lambda expression--->Use premise
    - 2.If available,Write it directly()->{}
    - 3.Fill in parentheses--->The formal parameters of abstract methods in functional interfaces are consistent
    - 4.Fill in braces--->Override the method body required by the functional interface abstract method
  Omission rule
    - Parameter types in parentheses can be omitted
    - There is only one parameter in parentheses,Then parentheses can also be omitted
    - If there is only one statement in braces,So braces,return keyword,Semicolons can also be omitted(The three should be omitted together)
  Use premise: Functional interface

- The stream can be obtained by collection, mapping or array
   use Collection of stream method
   use Stream Streaming of method
      
- Be able to master common flow operations
   forEach,count,filter,limit,skip,concat,map
- The content of the stream can be collected into collections and arrays
  Object[] toArray();
  stream.collect(Collectors.toList()) Collected List aggregate
  stream.collect(Collectors.toSet()) Collected Set aggregate

Keywords: Java

Added by nuying117 on Wed, 05 Jan 2022 09:42:39 +0200