1. Basic Concepts

  • Stream is the key abstraction for dealing with collections in Java8. It can specify what you want to do with collections, and can perform very complex operations like finding, filtering, and mapping data
  • “Sets are about data, streams are about computation!”
  • ① The Stream does not store elements by itself. ②Stream does not change the source object. Instead, they return a new Stream holding the result. ③ The Stream operation is delayed. This means they wait until they need results.
  • The operation of Stream takes three steps
    • Create Stream: A data source (e.g., collection, array) and get a Stream
    • Intermediate operations: A chain of intermediate operations that process data from a data source
    • Termination operation: A termination operation that performs an intermediate chain of operations and produces a result

Create a Stream

  • CollectionJava8 extends two methods for retrieving streams:
    • default Stream<E> stream() : Returns a sequential stream
    • default Stream<E> parallelStream(): Returns a parallel stream
      @Test
      public void test(a) {
        List<Integer> integers = Arrays.asList(1.2.3.4.5);
        Stream<Integer> stream = integers.stream();
        stream.forEach(System.out::println);
    
        Stream<Integer> parallelStream = integers.parallelStream();
        parallelStream.forEach(System.out::println);  // The output is not in order.
      }
    Copy the code
  • ArraysStatic method ofstream()Can get an array stream
      @Test
      public void test2(a) {
        int[] ints = {1.2.3.4};
        IntStream stream = Arrays.stream(ints);
        stream.forEach(System.out::println);
    
        double[] doubles = {1.0.2.0.3.0.4.0};
        DoubleStream doubleStream = Arrays.stream(doubles);
        doubleStream.forEach(System.out::println);
      }
    Copy the code
  • StreamStatic method ofof()Creating a stream
      @Test
      public void test3(a) {
        Stream<Integer> stream = Stream.of(1.2.3);  // The arrays.stream () method is still called internally
        stream.forEach(System.out::println);
      }
    Copy the code
  • Create infinite streams: can be created by static methodsStream.iterate()Stream.generate()Create an infinite stream.
      @Test
      public void test4(a) {
        Stream<Integer> stream = Stream.iterate(0, (x) -> x + 2);
        stream.limit(10).forEach(System.out::println);
      }
    
      @Test
      public void test5(a) {
        Stream<Integer> stream = Stream.generate(() -> 1);
        stream.limit(10).forEach(System.out::println);
      }
    Copy the code

    Stream.iterate() requires a seed as the starting value, as input to the UnaryOperator interface (a subinterface of the Function)

    Stream.generate()I need to pass one insupplierinterface

Stream intermediate operation

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

3.1 Screening and sectioning

  • filterFilter inappropriate, need to enter onePredicateFunction interface
      @Test
      public void test6(a) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(0.new BigDecimal(10000), "Amy"));
        employees.add(new Employee(1.new BigDecimal(9000), "John"));
        employees.add(new Employee(3.new BigDecimal(8000), "Jerry"));
        employees.add(new Employee(2.new BigDecimal(7000), "Taylor"));
    
        employees.stream()
                .filter((e) -> e.getSalary().compareTo(new BigDecimal(8000)) > 0)
                .forEach(System.out::println);
      }
    Copy the code
  • distinctduplicate removal
      @Test
      public void test7(a) {
        List<Integer> integers = Arrays.asList(1.2.3.4.5.1.2.3.2.6.7.8);
        Stream<Integer> stream = integers.stream();
        stream.distinct().forEach(System.out::println);
      }
    Copy the code

    If an object is unweighted, you need to have the object’s class implement hasCode() and equals methods, otherwise the underlying layer will compare the addresses and discover that they are different and cannot be unweighted

  • limitTruncates the stream, limiting the number of elements to a specified number
      @Test
      public void test5(a) {
        Stream<Integer> stream = Stream.generate(() -> 1);
        stream.limit(10).forEach(System.out::println);
      }
    Copy the code
  • skipSkip the first n elements
      @Test
      public void test9(a) {
        List<Integer> integers = Arrays.asList(1.2.3.4.5.6.7.8.9.10);
        Stream<Integer> stream = integers.stream();
        stream.skip(3).forEach(System.out::println);  // Skip the first three
      }
    Copy the code

3.2 mapping

  • mapTake as an argument a function that is applied to each element and mapped to a new element
      @Test
      public void test10(a) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(0.new BigDecimal(10000), "Amy"));
        employees.add(new Employee(1.new BigDecimal(9000), "John"));
        employees.add(new Employee(3.new BigDecimal(8000), "Jerry"));
        employees.add(new Employee(2.new BigDecimal(7000), "Taylor"));
    
        employees.stream()
                .map(Employee::getName)   // Class name :: method name
                .forEach(System.out::println);
      }
    Copy the code
  • mapToIntTake as an argument a function that is applied to each element, producing a new IntStream
      @Test
      public void test11(a) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(0.new BigDecimal(10000), "Amy"));
        employees.add(new Employee(1.new BigDecimal(9000), "John"));
        employees.add(new Employee(3.new BigDecimal(8000), "Jerry"));
        employees.add(new Employee(2.new BigDecimal(7000), "Taylor"));
    
        employees.stream()
                .mapToInt(Employee::getId)   // Class name :: method name
                .forEach(System.out::println);
      }
    Copy the code
  • flatMapIt’s a nesting doll. It can be nested in the methodmap, you can amortize a multidimensional array
      @Test
      public void test12(a) {
        Employee[][] employees = {
                {new Employee(0.new BigDecimal(10000), "Amy"), new Employee(1.new BigDecimal(9000), "John")},
                {new Employee(3.new BigDecimal(8000), "Jerry")},
                {new Employee(2.new BigDecimal(7000), "Taylor"), new Employee(4.new BigDecimal(6000), "Swift")}}; Arrays.stream(employees).flatMap(Arrays::stream).forEach(System.out::println);// For each one-dimensional array, also through arrays.stream
        Arrays.stream(employees)
                .flatMap((es) -> Arrays.stream(es).map(Employee::getName))  // For each one-dimensional array, convert to stream and use the mapping
                .forEach(System.out::println);
      }
    Copy the code

3.3 the sorting

  • sortedGenerates a new stream, which can be ordered either naturally or in a custom way (passed in is required)ComparatorThe or class itself is already implementedComparable)
      @Test
      public void test13(a) {
        List<Employee> employees = new ArrayList<>();
        employees.add(new Employee(0.new BigDecimal(10000), "Amy"));
        employees.add(new Employee(1.new BigDecimal(9000), "John"));
        employees.add(new Employee(3.new BigDecimal(8000), "Jerry"));
        employees.add(new Employee(2.new BigDecimal(7000), "Taylor"));
        // Comparator.comparing(Employee::getSalary) gets a comparator that sorts by salary
        Stream<Employee> sorted = employees.stream().sorted(Comparator.comparing(Employee::getSalary));
        //Stream
            
              sorted = employees.stream().sorted((o1, o2) -> o1.getSalary().compareTo(o2.getSalary())); // Before and after the equivalent
            
        sorted.forEach(System.out::println);
      }
    
      @Test
      public void test14(a) {
        List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
        integers.stream().sorted().forEach(System.out::println);   // Use natural sort only if the type being compared is a basic data type or if the Comparable interface has been implemented
      }
    Copy the code

4. Terminate Stream

4.1 Search and Match

  • allMatchTo check that all elements match, you need to pass in an assertionPredicateinterface
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    boolean res = stream.allMatch((x) -> x > 0);
    System.out.println(res);  // false
    Copy the code
  • anyMatchCheck that at least one element matches
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    res = stream.anyMatch((x) -> x > 0);  // true
    System.out.println(res);
    Copy the code
  • noneMatchCheck that none of them match
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    res = stream.noneMatch((x) -> x <= 0);  //false
    System.out.println(res);
    Copy the code
  • findFirstReturns the first element
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    Optional<Integer> first = stream.sorted().findFirst();  // get the first one
    Integer integer;
    if (first.isPresent()){
      integer = first.get();
      System.out.println(integer);  / / - 10
    }
    Copy the code
  • findAnyReturns any element
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    Optional<Integer> any = stream.findAny();   // Pick any one, but not random
    if (any.isPresent()) {
      integer = any.get();
      System.out.println(integer);
    }
    Copy the code
  • countReturns the total number of elements in the stream
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    long count = stream.count();  / / count
    System.out.println(count);
    Copy the code
  • maxMaximum value in return to Shanghai current
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    Optional<Integer> max = stream.max(Integer::compareTo);  // Find the maximum value
    if (max.isPresent()) {
      integer = max.get();
      System.out.println(integer);
    }
    Copy the code
  • minReturns the minimum value in the stream
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    Optional<Integer> min = stream.min(Integer::compareTo);  // Find the minimum value
    if (min.isPresent()) {
      integer = min.get();
      System.out.println(integer);
    }    
    Copy the code
  • forEachInternal iteration, see above

4.2 reduction

  • reduceCombine the elements of the stream repeatedly to obtain a value
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    
    Optional<Integer> reduce = stream.reduce(Integer::sum);  // You can combine elements in the stream repeatedly to get a value. For peace!
    if (reduce.isPresent()) {
      integer = reduce.get();
      System.out.println(integer);
    }
    Copy the code

4.3 to collect

  • collectChange the flow to another form. By receiving aCollectorInterface to summary elements in the stream
  • Usually byCollectorsGet utility classesCollector
    List<Integer> integers = Arrays.asList(4.58.6.4.33, -8, -7, -10);
    Stream<Integer> stream = integers.stream();
    List<Integer> collect = stream.collect(Collectors.toList());
    System.out.println(collect);
    
    stream = integers.stream();
    Set<Integer> collect1 = stream.collect(Collectors.toSet());
    System.out.println(collect1);
    
    List<String> strings = Arrays.asList("1"."2"."3");
    Stream<String> stream1 = strings.stream();
    String collect2 = stream1.collect(Collectors.joining());  // Combine strings into a single String, delimited by Spaces by default. Delimiters can be entered
    System.out.println(collect2);
    Copy the code
  • Specific methods and examples

Parallel stream and serial stream

  • A parallel stream is a stream that splits a piece of content into chunks of data and uses different threads to process each chunk separately.
  • The Stream API can be declaratively passedparallel()sequential()Switch between parallel and sequential streams.
      @Test
      public void test16(a) {
        List<Integer> list = new ArrayList<>();
        for (int i = 0; i < 100000000; i++) {
          list.add(i);
        }
    
        Instant start = Instant.now();
        int sum = list.stream().parallel().mapToInt(x -> x).sum();
        //sum = list.parallelStream().mapToInt(x -> x).sum();
        Instant end = Instant.now();
        System.out.println(sum);
        System.out.println("Take time" + Duration.between(end, start));
      }
    Copy the code