Java-stream Stream computing

1, an overview of the

There are two most important changes in Java8. The first is a Lambda expression; The other is the Stream API.

The Stream API (java.util.stream) brings a true functional programming style to Java. This is by far the best addition to the Java class library, because the Stream API can greatly increase the productivity of Java programmers, allowing programmers to write efficient, clean, and concise code.

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. Manipulating collection data using the Stream API is similar to database queries executed using SQL. You can also use the Stream API to perform operations in parallel. In short, the Stream API provides an efficient and easy-to-use way to process data.

Why use the Stream API

In practice, most of the data sources in the project come from Mysql, Oracle, etc. But now there are more data sources, such as MongDB, Radis, etc., and these NoSQL data need to be processed at the Java level.

The difference between a Stream and a Collection: A Collection is a static in-memory data structure, while a Stream is about computation. The former is mainly memory oriented and stored in memory, while the latter is mainly CPU oriented and computes by CPU.

What is a Stream

What exactly is a Stream? Is a data channel used to manipulate sequences of elements generated by data sources (collections, arrays, and so on). “Collections are about data, streams are about computation!”

Stream provides a high-level abstraction of Java collection operations and expressions in an intuitive manner similar to querying data from a database with SQL statements. The Stream API can greatly improve the productivity of Java programmers, allowing programmers to write efficient, clean, and concise code. The collection of elements to be processed in this style is treated as a stream, which is transmitted in a pipe and can be processed on nodes of the pipe, such as filter, Map, Reduce, find, match, sorted, and so on.

The element stream is processed by intermediate operation in the pipe, and finally the result of the previous processing is obtained by terminal operation.

+--------------------+       +------+   +------+   +---+   +-------+
| stream of elements +-----> |filter+-> |sorted+-> |map+-> |collect|
+--------------------+       +------+   +------+   +---+   +-------+
Copy the code

The above process is translated into Java code:

List<Integer> transactionsIds = 
widgets.stream()
             .filter(b -> b.getColor() == RED)
             .sorted((x,y) -> x.getWeight() - y.getWeight())
             .mapToInt(Widget::getWeight)
             .sum();
Copy the code

Note:

  • The Stream itself does not store elements.
  • Stream does not change the source object. Instead, they return a new Stream holding the result.
  • The Stream operation executes lazily. This means that they wait until they need the result (terminate the operation).
  • Unlike the previous Collection operation, the Stream operation has two basic characteristics:
    • Pipelining: All intermediate operations return the flow object itself. These operations can be cascaded into a pipe, as in fluent style. This allows you to optimize operations, such as delay and short-circuiting.
    • Internal iteration: Previously, collections were iterated explicitly outside the collection using either Iterator or for-each. This is called external iteration. A Stream provides a means of iterating internally through a Visitor pattern.

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 (terminal operation) : Once the termination operation is performed, the intermediate operation chain is executed and the result is produced. After that, it won’t be used again

2. Stream instantiation

2.1. Create a Stream through a collection

The Collection interface in Collection Java8 is extended to provide two methods for retrieving streams:

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

default Stream<E> stream() : Returns a sequential stream

public class Demo1 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("123");
        arrayList.add("124");
        arrayList.add("125");
        arrayList.add("126");

        Stream<String> stream = arrayList.stream();
              
        // We call the terminate operation directly to traverse the contents of the streamstream.forEach(System.out :: println); }}Copy the code

Calling the stream() method with the collection returns a sequential stream

  • This is a sequential stream, because this stream is loading the elements of the collection element by element, and this stream is loading them in the order they were loaded
  • This method is defined in the interface, so this method is declared asDefault (default)
  • Here we say that the method is defined in the interface, not just that the method is declared in the interface, but that the implementation of the method is also implemented in the interface, in which case the implementation method in the interface is defined asdefaultThe method of

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

public class Demo1 {
    public static void main(String[] args) {
        ArrayList<String> arrayList = new ArrayList<>();
        arrayList.add("123");
        arrayList.add("124");
        arrayList.add("125");
        arrayList.add("126");

        Stream<String> stream = arrayList.parallelStream();
              
        // We call the terminate operation directly to traverse the contents of the streamstream.forEach(System.out :: println); }}Copy the code

Calling the parallelStream() method with collections gives us a parallelStream object

  • It’s going to return a parallel stream, because at this point the stream is loading the elements of the set several at a time several at a time, just like we did with multithreading, we’re loading multiple at a time, we’re doing concurrent operations, so there’s no guarantee of order, So at this point we get parallel stream objects that are not in the order of our original collection
  • This method is also defined in the interface, so we need to implement this method in the interface, so we can only declare this method as default.
  • When a method is declared default in an interface, it is no longer abstract and can have a body

2.2. Create Stream through an array

We get Arrays from the Java8 static stream() method of Arrays:

  • static < T> Stream< T> stream() : Returns a stream

An overloaded form that can handle arrays corresponding to primitive types:

  • public static IntStream stream(int[] array)
  • public static LongStream stream(long[] array)
  • public static DoubleStream stream(double[] array)

Example 1

public class Demo3 {
    public static void main(String[] args) {
        int [] arr  = new int[] {1.2.3.4.5};

        /* This is done by calling the stream() method of the Arrays class, Then we pass in the array of type int that we created as an argument to this method, and then we get an object of type IntStream public static IntStream stream(int[] array) */
        IntStream intStream = Arrays.stream(arr);

        /* The Stream object is traversed directly by calling a termination operation on the Stream objectintStream.forEach(System.out :: println); }}Copy the code

Example 2: Custom type

public class Employee {
    private int age;
    private String name;
    public Employee(a){}public Employee(int age, String name){
        this.age = age;
        this.name = name;
    }

    @Override
    public String toString(a) {
        return "Employee{" +
            "age=" + age +
            ", name='" + name + '\' ' +
            '} '; }}Copy the code

Then we create an array of Employee, and then we get the corresponding stream object by using the stream() method from the Arrays class

public class Demo2 {
    public static void main(String[] args) {

        Employee e1 = new Employee(20."马云");
        Employee e2 = new Employee(30.Ma Huateng);

        Employee [] arr = new Employee[]{e1,e2};

        Static 
      
        stream 
       
         stream() : This method is a generic method, and the generics of this generic method are determined by the type of the array that is passed to the method so the return value of this method, the generic of the Stream object that is returned, is the type of the array that is passed to this method as arguments */
       
      
        Stream<Employee> stream = Arrays.stream(arr);

        /* Instead of using an intermediate operation, we directly use the termination operation to output the data in the stream */stream.forEach(System.out :: println); }}Copy the code

Static < T> Stream< T> Stream ();

  • The return value of this method isStream< T>In this case, the return value is represented as a generic type
  • This method is called because our stream() method is passing in an array that references a type as a type

Create a Stream by using the static of() method of the Stream class

You can call the Stream class static method of() to create a Stream by displaying values. It can accept any number of parameters.

public static Stream of(T… Values) : Returns a stream

  • This method takes a deformable parameter.
  • A morphable parameter is essentially an array
  • This method is a generic method
  • This method is a static method

The instance

import java.util.stream.Stream;
public class Demo4 {
    public static void main(String[] args) {
        Stream<Integer> stream = Stream.of(1.2.3.4.5); stream.forEach(System.out :: println); }}Copy the code

Create an infinite Stream

There are two ways to create an infinite stream:

The iteration

  • The iteration, call the method:public static <T> Stream<T> iterate(final T seed , final UnavyOperator<T> f);
    • This method is a static method
    • This method is a generic method
    • The first argument to this method is a seed from which to start, and the second argument to this method is a unary functional interface
    • The input parameter of the UnavyOperator interface is of the same type as the return value. This interface is a subinterface of the Function interface

Example: At this point we create an infinite stream and use this infinite stream to traverse the first ten even numbers

public class Demo5 {
    public static void main(String[] args) {
        /* We use the iterate() method to get an infinite stream object, and then we limit the number of times by using an intermediate operation limit(). Then we use the terminate operation to iterate over the infinite stream object */
        Stream.iterate(0,t -> t + 2).limit(10).forEach(System.out :: println); }}Copy the code

generate

Public static

stream

generate(Supplier

s)


  • This method is a static method
  • This method is a generic method
  • This method takes a Supplier interface object (a Supplier functional interface object)
  • The Supplier interface takes no arguments, but has a return value

** Example: ** At this point we create an infinite stream and use this infinite stream to generate ten numbers between 0.0 and 1.0 (can be 0.0, but not 1.0)

public class Demo6 {
    public static void main(String[] args) {
        /* We create an infinite stream object, then call the intermediate operation to limit the number of times executed, and then call the termination operation to print the stream */
        Stream.generate(Math :: random).limit(10).forEach(System.out :: println); }}Copy the code

3. 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! Processing all at once when terminating an operation is called lazy evaluation

Conditions to prepare

public class Employee {

    private int id;
    private String name;
    private int age;
    private double salary;

    public int getId(a) {
        return id;
    }

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

    public String getName(a) {
        return name;
    }

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

    public int getAge(a) {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public double getSalary(a) {
        return salary;
    }

    public void setSalary(double salary) {
        this.salary = salary;
    }

    public Employee(a) {}

    public Employee(int id) {
        this.id = id;
    }

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

    public Employee(int id, String name, int age, double salary) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
    }

    @Override
    public String toString(a) {
        return "Employee{" + "id=" + id + ", name='" + name + '\' ' + ", age=" + age + ", salary=" + salary + '} ';
    }

    @Override
    public boolean equals(Object o) {
        if (this == o) {
            return true;
        }
        if (o == null|| getClass() ! = o.getClass()) {return false;
        }

        Employee employee = (Employee)o;

        if(id ! = employee.id) {return false;
        }
        if(age ! = employee.age) {return false;
        }
        if(Double.compare(employee.salary, salary) ! =0) {
            return false;
        }
        returnname ! =null ? name.equals(employee.name) : employee.name == null;
    }

    @Override
    public int hashCode(a) {
        int result;
        long temp;
        result = id;
        result = 31* result + (name ! =null ? name.hashCode() : 0);
        result = 31 * result + age;
        temp = Double.doubleToLongBits(salary);
        result = 31 * result + (int)(temp ^ (temp >>> 32));
        returnresult; }}Copy the code

The test class

public class EmployeeData {

    public static List<Employee> getEmployees(a) {
        List<Employee> list = new ArrayList<>();

        list.add(new Employee(1001.Ma Huateng.34.6000.38));
        list.add(new Employee(1002."马云".12.9876.12));
        list.add(new Employee(1003."Liu Qiangdong".33.3000.82));
        list.add(new Employee(1004."Lei jun".26.7657.37));
        list.add(new Employee(1005.Robin Li.65.5555.32));
        list.add(new Employee(1006."Bill Gates".42.9500.43));
        list.add(new Employee(1007."Ren Zhengfei".26.4333.32));
        list.add(new Employee(1008."Zuckerberg".35.2500.32));

        returnlist; }}Copy the code

3.1. Screening and slicing

The instance

@Test
public void test1(a) {
    List<Employee> list = EmployeeData.getEmployees();
    // Filter (Predicate P)- Receives Lambda, excludes certain elements from the stream.
    Stream<Employee> stream = list.stream();
    Select * from employee table where salary > 7000
    stream.filter(e -> e.getSalary() > 7000).forEach(System.out::println);
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}

    System.out.println();

    // limit(n)- truncates the stream so that it does not exceed a given number of elements.
    // stream.limit(3).forEach(System.out::println); // Closed has been closed and needs to be regenerated
    list.stream().limit(3).forEach(System.out::println);
    // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1003, name=' salary ', age=33, salary=3000.82}

    System.out.println();

    // skip(n)- Skip the element, returning a stream with the first n elements thrown away. If the stream contains less than n elements, then
    list.stream().skip(3).forEach(System.out::println);
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
    // Employee{id=1005, name=' salary ', age=65, salary=5555.32}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}
    // Employee{id=1007, name=' ren ', age=26, salary=4333.32}
    // Employee{id=1008, name=' zuckerberg ', age=35, salary=2500.32}

    System.out.println();

    // distinct()- Filter to remove duplicate elements by hashCode() and equals() of the elements generated by the stream
    list.add(new Employee(1010."Liu Qiangdong".40.8000));
    list.add(new Employee(1010."Liu Qiangdong".42.8000));
    list.add(new Employee(1010."Liu Qiangdong".40.8000));
    list.add(new Employee(1010."Liu Qiangdong".40.8000));
    list.add(new Employee(1010."Liu Qiangdong".40.8000));

    // System.out.println(list);
    // [Employee{id= 1000, name=' ma ', age=34, salary=6000.38}, Employee{id=1002, name=' Ma ', age=12, salary=9876.12},
    // Employee{id=1003, name=' liu Qiongdong ', age=33, salary=3000.82}, Employee{id=1004, name=' Liu Qiongdong ', age=26, salary=7657.37},
    // Employee{id=1005, name=' salary ', age=65, salary=5555.32}, Employee{id=1006, name=' Bill Gates ', age=42,
    // salary=9500.43}, Employee{id=1007, name=' ren ', age=26, salary=4333.32}, Employee{ID =1008, name=' zach ',
    // age=35, salary=2500.32}, Employee{id=1010, name='刘强东', age=40, salary=8000.0}, Employee{id=1010, name='刘强东',
    // age=42, salary=8000.0}, Employee{id=1010, name= 8000.0}, Employee{id=1010, name=' 8000.0 ',
    // age=40, salary=8000.0}, age=40, salary=8000.0}]

    System.out.println();

    list.stream().distinct().forEach(System.out::println);
    // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1003, name=' salary ', age=33, salary=3000.82}
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
    // Employee{id=1005, name=' salary ', age=65, salary=5555.32}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}
    // Employee{id=1007, name=' ren ', age=26, salary=4333.32}
    // Employee{id=1008, name=' zuckerberg ', age=35, salary=2500.32}
    // Employee{id=1010, name=' salary ', age=40, salary=800}
    // Employee{id=1010, name=' salary ', age=42, salary=800}
}
Copy the code

3.2, mapping,

The instance

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

    System.out.println();

    // Exercise 1: Get the names of employees whose names are longer than 3.
    List<Employee> employees = EmployeeData.getEmployees();
    Stream<String> namesStream = employees.stream().map(Employee::getName);
    namesStream.filter(name -> name.length() > 3).forEach(System.out::println);
    // Bill Gates
    // Mark Zuckerberg

    System.out.println();

    // Exercise 2:
    Stream<Stream<Character>> streamStream = list.stream().map(StreamAPITest1::fromStringToStream);
    streamStream.forEach(s -> {
        s.forEach(System.out::println);
    });
    // a
    // a
    // b
    // b
    // c
    // c
    // d
    // d

    System.out.println();

    // flatMap is preferred for traversal
    // flatMap(Function f)- Takes a Function as an argument, replaces every value in the stream with another stream, and concatenates all streams into a single stream.
    Stream<Character> characterStream = list.stream().flatMap(StreamAPITest1::fromStringToStream);
    characterStream.forEach(System.out::println);
    // a
    // a
    // b
    // b
    // c
    // c
    // d
    // d
}

// Convert a collection of multiple characters in a string to an instance of the corresponding Stream
public static Stream<Character> fromStringToStream(String str) {// a
    ArrayList<Character> list = new ArrayList<>();
    for (Character c : str.toCharArray()) {
        list.add(c);
    }
    return list.stream();
}

@Test
public void test3(a) {
    ArrayList list1 = new ArrayList();
    list1.add(1);
    list1.add(2);
    list1.add(3);

    ArrayList list2 = new ArrayList();
    list2.add(4);
    list2.add(5);
    list2.add(6);

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

    list1.addAll(list2);
    // [1, 2, 3, 4, 5, 6]
    System.out.println(list1);
}
Copy the code

3.3, sorting,

The instance

/ / 3 - sort
@Test
public void test4(a) {
    Sorted ()- sorted naturally
    List<Integer> list = Arrays.asList(12.43.65.34.87.0, -98.7);
    list.stream().sorted().forEach(System.out::println);
    / / - 98
    / / 0
    / / 7
    / / 12
    / / 34
    / / 43
    / / 65
    / / 87

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

    Sorted (Comparator com)- Custom sorted

    // List<Employee> employees = EmployeeData.getEmployees();
    // employees.stream().sorted((e1, e2) -> Integer.compare(e1.getAge(),
    // e2.getAge())).forEach(System.out::println);
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
    // Employee{id=1007, name=' ren ', age=26, salary=4333.32}
    // Employee{id=1003, name=' salary ', age=33, salary=3000.82}
    // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
    // Employee{id=1008, name=' zuckerberg ', age=35, salary=2500.32}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}
    // Employee{id=1005, name=' salary ', age=65, salary=5555.32}

    List<Employee> employees = EmployeeData.getEmployees();
    employees.stream().sorted((e1, e2) -> {
        int ageValue = Integer.compare(e1.getAge(), e2.getAge());
        if(ageValue ! =0) {
            return ageValue;
        } else {
            // Same age, in ascending order of salary
            return Double.compare(e1.getSalary(), e2.getSalary());
            // Same age, in ascending order of salary
            // return -Double.compare(e1.getSalary(), e2.getSalary());
        }
    }).forEach(System.out::println);
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1007, name=' ren ', age=26, salary=4333.32}
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
    // Employee{id=1003, name=' salary ', age=33, salary=3000.82}
    // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
    // Employee{id=1008, name=' zuckerberg ', age=35, salary=2500.32}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}
    // Employee{id=1005, name=' salary ', age=65, salary=5555.32}
}
Copy the code

4. Terminate Stream

Terminal operations generate results from the pipeline of streams. The result can be any value that is not a stream, such as List, Integer, or even void. After a stream has been terminated, it cannot be used again and must be generated again.

4.1. Match and search

The instance

package com.streamAPI;

import java.util.Arrays;
import java.util.List;
import java.util.Optional;
import java.util.Set;
import java.util.stream.Collectors;
import java.util.stream.Stream;

import org.junit.Test;

/** * Stream terminates ** /
public class StreamAPITest2 {

    // 1- match and find
    @Test
    public void test1(a) {

        List<Employee> employees = EmployeeData.getEmployees();
        // allMatch(Predicate P) - Checks if all elements match.
        // Exercise: Are all employees older than 18
        boolean allMatch = employees.stream().allMatch(e -> e.getAge() > 18);
        // false
        System.out.println(allMatch);

        // anyMatch(Predicate P) - Checks if at least one element matches.
        // Exercise: Is there any employee whose salary is greater than 10000
        boolean anyMatch = employees.stream().anyMatch(e -> e.getSalary() > 10000);
        // false
        System.out.println(anyMatch);

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

        FindFirst - Returns the first element
        Optional<Employee> employee = employees.stream().findFirst();
        // Optional[Employee{id= 1000, name=' ma ', age=34, salary=6000.38}]
        System.out.println(employee);

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

    }

    @Test
    public void test2(a) {
        List<Employee> employees = EmployeeData.getEmployees();

        // count - Returns the total number of elements in the stream
        long count = employees.stream().filter(e -> e.getSalary() > 5000).count();
        / / 5
        System.out.println(count);

        // Max (Comparator c) - Returns the maximum value in the stream
        // Exercise: return the highest salary:
        Stream<Double> salaryStream = employees.stream().map(e -> e.getSalary());
        Optional<Double> maxSalary = salaryStream.max(Double::compare);
        / / Optional [9876.12]
        System.out.println(maxSalary);

        // min(Comparator c) - Returns the minimum value in the stream
        // Exercise: return minimum wage employee
        Optional<Employee> employee =
            employees.stream().min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        // Optional[Employee{id=1008, name=' zuckerberg ', age=35, salary=2500.32}]
        System.out.println(employee);

        System.out.println();

        ForEach (Consumer C) - Internal iteration
        employees.stream().forEach(System.out::println);
        // Use the set traversal operation, the effect is the same, as follows:
        employees.forEach(System.out::println);
        // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
        // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
        // Employee{id=1003, name=' salary ', age=33, salary=3000.82}
        // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
        // Employee{id=1005, name=' salary ', age=65, salary=5555.32}
        // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}
        // Employee{id=1007, name=' ren ', age=26, salary=4333.32}
        // Employee{id=1008, name=' zuckerberg ', age=35, salary=2500.32}
    }
Copy the code

4.2 and reduction

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

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

    // reduce(BinaryOperator) - Can combine elements of the stream repeatedly to obtain a value. Returns the Optional < T >
    // Exercise 2: Calculate the sum of the salaries of all employees in the company
    List<Employee> employees = EmployeeData.getEmployees();
    Stream<Double> salaryStream = employees.stream().map(Employee::getSalary);
    // Optional<Double> sumMoney = salaryStream.reduce(Double::sum);
    Optional<Double> sumMoney = salaryStream.reduce((d1, d2) -> d1 + d2);
    / / Optional [48424.08]
    System.out.println(sumMoney);
}

Copy the code

4.3, collection

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

/ / 3 - collection
@Test
public void test4(a) {
    Collect (Collector C): Convert the stream to another form. Receives an implementation of the Collector interface, a method for summarizing elements in a Stream
    // Exercise 1: Find employees whose salaries are greater than 6000 and return a List or Set

    List<Employee> employees = EmployeeData.getEmployees();
    List<Employee> employeeList = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toList());
    employeeList.forEach(System.out::println);
    // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}

    System.out.println();

    Set<Employee> employeeSet = employees.stream().filter(e -> e.getSalary() > 6000).collect(Collectors.toSet());
    employeeSet.forEach(System.out::println);
    // Employee{id= 1000, name=' salary ', age=34, salary=6000.38}
    // Employee{id=1002, name=' ma ', age=12, salary=9876.12}
    // Employee{id=1006, name=' Bill Gates ', age=42, salary=9500.43}
    // Employee{id=1004, name=' salary ', age=26, salary=7657.37}}}Copy the code

In addition, the Collectors class provides many static methods to easily create common collector instances. The following table describes the methods and instances.

5, practice

Exercise 1:

import java.util.ArrayList;
import java.util.Arrays;
import java.util.IntSummaryStatistics;
import java.util.List;
import java.util.Random;
import java.util.stream.Collectors;
import java.util.Map;

public class Java8Tester {
    public static void main(String args[]){
        System.out.println("Using Java 7:");

        // Evaluates the empty string
        List<String> strings = Arrays.asList("abc".""."bc"."efg"."abcd".""."jkl");
        System.out.println("List:" +strings);
        long count = getCountEmptyStringUsingJava7(strings);

        System.out.println("The number of null characters is:" + count);
        count = getCountLength3UsingJava7(strings);

        System.out.println("The number of strings of length 3 is:" + count);

        // Delete the empty string
        List<String> filtered = deleteEmptyStringsUsingJava7(strings);
        System.out.println("Filtered list:" + filtered);

        // Delete empty strings and merge them with commas
        String mergedString = getMergedStringUsingJava7(strings,",");
        System.out.println("Merge string:" + mergedString);
        List<Integer> numbers = Arrays.asList(3.2.2.3.7.3.5);

        // Get the square number of list elements
        List<Integer> squaresList = getSquares(numbers);
        System.out.println("List of squares:" + squaresList);
        List<Integer> integers = Arrays.asList(1.2.13.4.15.6.17.8.19);

        System.out.println("List:" +integers);
        System.out.println("Maximum number in list:" + getMax(integers));
        System.out.println("Smallest number in list:" + getMin(integers));
        System.out.println("Sum of all numbers:" + getSum(integers));
        System.out.println("Average:" + getAverage(integers));
        System.out.println("Random number:");

        // Outputs 10 random numbers
        Random random = new Random();

        for(int i=0; i < 10; i++){
            System.out.println(random.nextInt());
        }

        System.out.println("Using Java 8:");
        System.out.println("List:" +strings);

        count = strings.stream().filter(string->string.isEmpty()).count();
        System.out.println("The number of empty strings is: + count);

        count = strings.stream().filter(string -> string.length() == 3).count();
        System.out.println("The number of strings of length 3 is:"+ count); filtered = strings.stream().filter(string ->! string.isEmpty()).collect(Collectors.toList()); System.out.println("Filtered list:"+ filtered); mergedString = strings.stream().filter(string ->! string.isEmpty()).collect(Collectors.joining(","));
        System.out.println("Merge string:" + mergedString);

        squaresList = numbers.stream().map( i ->i*i).distinct().collect(Collectors.toList());
        System.out.println("Squares List: " + squaresList);
        System.out.println("List:" +integers);

        IntSummaryStatistics stats = integers.stream().mapToInt((x) ->x).summaryStatistics();

        System.out.println("Maximum number in list:" + stats.getMax());
        System.out.println("Smallest number in list:" + stats.getMin());
        System.out.println("Sum of all numbers:" + stats.getSum());
        System.out.println("Average:" + stats.getAverage());
        System.out.println("Random number:");

        random.ints().limit(10).sorted().forEach(System.out::println);

        // Parallel processing
        count = strings.parallelStream().filter(string -> string.isEmpty()).count();
        System.out.println("The number of empty strings is: + count);
    }

    private static int getCountEmptyStringUsingJava7(List<String> strings){
        int count = 0;

        for(String string: strings){

            if(string.isEmpty()){ count++; }}return count;
    }

    private static int getCountLength3UsingJava7(List<String> strings){
        int count = 0;

        for(String string: strings){

            if(string.length() == 3){ count++; }}return count;
    }

    private static List<String> deleteEmptyStringsUsingJava7(List<String> strings){
        List<String> filteredList = new ArrayList<String>();

        for(String string: strings){

            if(!string.isEmpty()){
                filteredList.add(string);
            }
        }
        return filteredList;
    }

    private static String getMergedStringUsingJava7(List<String> strings, String separator){
        StringBuilder stringBuilder = new StringBuilder();

        for(String string: strings){

            if(! string.isEmpty()){ stringBuilder.append(string); stringBuilder.append(separator); } } String mergedString = stringBuilder.toString();return mergedString.substring(0, mergedString.length()-2);
    }

    private static List<Integer> getSquares(List<Integer> numbers){
        List<Integer> squaresList = new ArrayList<Integer>();

        for(Integer number: numbers){
            Integer square = new Integer(number.intValue() * number.intValue());

            if(!squaresList.contains(square)){
                squaresList.add(square);
            }
        }
        return squaresList;
    }

    private static int getMax(List<Integer> numbers){
        int max = numbers.get(0);

        for(int i=1; i < numbers.size(); i++){ Integer number = numbers.get(i);if(number.intValue() > max){ max = number.intValue(); }}return max;
    }

    private static int getMin(List<Integer> numbers){
        int min = numbers.get(0);

        for(int i=1; i < numbers.size(); i++){ Integer number = numbers.get(i);if(number.intValue() < min){ min = number.intValue(); }}return min;
    }

    private static int getSum(List numbers){
        int sum = (int)(numbers.get(0));

        for(int i=1; i < numbers.size(); i++){ sum += (int)numbers.get(i);
        }
        return sum;
    }

    private static int getAverage(List<Integer> numbers){
        returngetSum(numbers) / numbers.size(); }}Copy the code

Execute the above script and the output is as follows:

$javac Java8Tester. Java $Java Java8Tester uses Java 7: list: [ABC, BC, EFg, ABCD, JKL] 3 Filter list: [ABC, BC, efg, abcd, JKL] Merge string: ABC, BC, efg, abcd, JKL Square list: [9, 4, 49, 25] List: [1, 2, 13, 4, 15, 6, 17, 8, 19] Maximum number in list: 19 Minimum number in list: 1 Sum of all numbers: 85 Average number: 9 Random number: -393170844-963842252 447036679-1043163142 881079698 221586850-1101570113 576190039-1045184578 1647841045 Using Java 8: List: [ABC,, BC, EFg, abCD, JKL] Number of empty strings: 2 Number of 3-length strings: 3 Filtered list: [ABC, BC, EFg, abCD, JKL] Combined string: JKL Squares List: ABC, BC, EFG, ABCD, JKL Squares List: [9, 4, 49, 25] 1 Sum of all numbers: 85 Average: 9.444444444444445 Random number: 1743813696-1301974944-1299484995-779981186 136544902 555792023 1243315896 1264920849 1472077135 1706423674 The number of empty strings is:  2Copy the code

Ex 2

Number square sort (flashback) output. The string is converted to map output

import java.util.List;
import java.util.Arrays;
import java.util.Map;
import java.util.HashMap;
import java.util.stream.Collectors;
class Main {
    public static void main(String[] args) {
        List<Integer> numbers = Arrays.asList(3.2.2.3.7.3.5);
        // Get the corresponding square
        // List
      
        squaresList = numbers.stream().map( i -> i*i).distinct().collect(Collectors.toList());
      
        List<Integer> squaresList = numbers.stream()
            .map(i -> i * i)
            .sorted((x, y) -> y - x)
            .collect(Collectors.toList());
        // squaresList.forEach(System.out::println);
        squaresList.forEach(num -> {
            num++;
            System.out.println(num);
        });

        List<String> strList = Arrays.asList("a"."ba"."bb"."abc"."cbb"."bba"."cab");
        Map<Integer, String> strMap = new HashMap<Integer, String>();

        strMap = strList.stream()
            .collect( Collectors.toMap( str -> strList.indexOf(str), str -> str ) );

        strMap.forEach((key, value) -> {
            System.out.println(key+"... ""+value); }); }}Copy the code

The output is:

50
26
10
10
10
5
5
0::a
1::ba
2::bb
3::abc
4::cbb
5::bba
6::cab
Copy the code