Magic data shuttle Stream API

Keywords: Java Back-end


When we do projects, we often need to integrate and filter the data, and judge after using the for loop every time. I believe you must be tired. Now the Lamda expression newly exited by Java 8 and Steam API can perfectly process the data and complete the function of shuttling between the data.
Stream means stream, which is slightly different from IO stream. We get the desired data by pipelining the data stream.

Create stream from Stream API

There are many ways to create a stream, including through the instance method. stream() of the collection, through the static method Arrays.stream() of the array tool class, through the static method Stream.of() of the stream class, and through Stream.iterate(); The last one is to create an infinite flow, that is, it runs all the time without ending.

Collection instance method creation

Creating a flow through the collection instance method is the form we generally use.

		// 1. The stream can be obtained through the stream() or parallel stream() provided by the Collection series Collection
        List<String> list = new ArrayList<>();
        Stream<String> stream = list.stream();

Create a stream using static methods of the array utility class

        // 2. The array stream can be obtained through the static method stream() in Arrays
        Employee[] emps = new Employee[10];
        Stream<Employee> stream1 = Arrays.stream(emps);

Stream static method of()

        // 3. Through the static method in Stream ()
        Stream<String> stream2 = Stream.of("aa", "bb", "vv");

Stream static methods iterate() and generate()

Stream's iterate() creates an infinite stream. What is an infinite stream? It means that the operation will never stop without terminating.

        // 4. Create an infinite stream
        // iteration
        Stream<Integer> stream3 = Stream.iterate(0, (x) -> x + 2);
        stream3.limit(10).forEach(System.out::println);

        // generate
        Stream.generate(() -> (Math.random()))
                .limit(5)
                .forEach(System.out::println);

Intermediate operations of Stream API

There are many intermediate operations in Stream API, such as filtering, specification, mapping, sorting, etc.
The intermediate operation of Stream has a distinct property: when the terminal operation is not executed, the intermediate operation is not executed; When the terminal operation is performed, the terminal operation is performed in the form of pipeline.

Screening and slicing

The Stream API provides methods for filtering and slicing data streams, which are:

filter -- receives Lamda and excludes elements from the stream.
limit -- truncate the stream so that its elements do not exceed the given number.
skip(n) -- skip elements and rush back to a stream that throws away the first n elements. If there are less than n elements in the stream, an empty stream is returned. Complementary to limit(n).
distinct -- remove the duplicate, and take out the duplicate elements through hanshcode() and equals() of the elements generated by the stream.

    @Test
    public void test5(){
        emps.stream()
                .distinct()
                .forEach(System.out::println);
    }

    @Test
    public void test4() {
        emps.stream()
                .filter((e) -> e.getSalary()<5000)
                .skip(2)
                .forEach(System.out::println);
    }

    @Test
    public void test3() {
        emps.stream()
                .filter((e) -> {
                    System.out.println("Short circuit!");
                    return e.getSalary() < 5000;
                })
                .limit(2)
                .forEach(System.out::println);
    }

    // Internal iteration: the iteration operation is completed by Stream API
    @Test
    public void test1() {
        // Intermediate operation: no processing will be performed
        Stream<Employee> s = emps.stream()
                .filter((e) -> {
                    System.out.println("Stream API Intermediate operation of");
                    return e.getAge() > 35;
                });
        // Terminate operation: all contents are executed at once, i.e. "lazy evaluation"
        s.forEach(System.out::println);
    }

mapping

In the Strame API, there are two APIs that provide mapping functions: map and flatMap.

map: take a function as a parameter, and each element in the stream will execute this function and reorganize the stream in the form of the return value of the function.
flatMap: take a function as a parameter, take each value in the stream as another stream, and then connect all streams into one stream.

The difference between map and flatMap is that no matter what type of value returned by the accepted function, flapMap arranges each element into a stream, and finally connects all streams into a stream, while map just puts the returned value into the stream.
For example, when the received function returns a stream, the map is finally combined into a nested stream in the stream, while the flapMap only returns the stream in which all elements are strung together.

    @Test
    public void test6() {
        List<String> list = Arrays.asList("aaa", "bb", "as", "ee");
        list.stream()
                .map((str) -> str.toUpperCase())
                .forEach(System.out::println);
        System.out.println("=======================");
        emps.stream()
                .map(Employee::getName)
                .forEach(System.out::println);
        System.out.println("=======================");
        Stream<Stream<Character>> stream = list.stream()
                .map(TestStreamAPI2::filterCharacter);
        stream.forEach((sm) -> {
            sm.forEach(System.out::println);
        });
        System.out.println("=======================");

        list.stream()
                .flatMap(TestStreamAPI2::filterCharacter)
                .forEach(System.out::println);
    }

sort

There is only one sorting method provided by Stream API, sorted(), but it has two methods: with and without parameters;

sorted() natural sort
sorted(Comparator com) -- customized sorting

    @Test
    public void test7() {
        List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd", "eee");
        list.stream()
                .sorted()
                .forEach(System.out::println);

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

        emps.stream()
                .sorted((x,y) -> {
                    if (x.getAge().equals(y.getAge())){
                        return x.getName().compareTo(y.getName());
                    }else {
                        return x.getAge().compareTo(y.getAge());
                    }
                }).forEach(System.out::println);
    }

Terminate operation

Stream provides a variety of termination API s, which can perfectly cooperate with intermediate operations to process data.

Find and match

allMatch -- check to see if all elements match
anyMatch -- check to see if at least one element matches
noneMatch -- check if all elements are not matched
findFirst -- returns the first element
findAny -- returns all elements in the current stream
count -- returns the total number of elements in the stream
max -- returns the maximum value in the stream
min -- minimum value in return flow

    @Test
    public void test2() {
        long count = emps.stream()
                .count();
        System.out.println(count);
        System.out.println("============================");
        Optional<Employee> max = emps.stream()
                .max((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
        System.out.println(max.get());
        System.out.println("============================");
//        Optional<Employee> min = emps.stream()
//                .min((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()));
//        System.out.println(min.get().getSalary());
        Optional<Double> min = emps.stream()
                .map(Employee::getSalary)
                .min(Double::compareTo);
        System.out.println(min.get());
    }

    @Test
    public void test1() {
        boolean b = emps.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b);
        System.out.println("===========================");
        boolean b1 = emps.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);
        System.out.println("===========================");
        boolean b2 = emps.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);
        System.out.println("===========================");
        Optional<Employee> op = emps.stream()
                .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(op.get());
        System.out.println("===========================");
        Optional<Employee> any = emps.stream()
                .filter((e) -> e.getStatus().equals(Employee.Status.FREE))
                .findAny();
        System.out.println(any.get());
    }

reduction

Reduce (t identity, binary operator) / reduce (binary operator) - you can combine the elements in the stream repeatedly to get a value.
The essence is recursion.

    @Test
    public void test3() {
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        // Find the number in the array. 0 is the initial value
        Integer sum = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(sum);
        System.out.println("=================================");
        Optional<Double> op = emps.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(op.get());
    }

collect

Because the collection operation is the most common in work, the collection operation method is very common.

collect -- convert the Stream to another form. Accept the implementation of a Collector interface, which is used to summarize the elements in the Stream.

@Test
    public void test10() {
        String str = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.joining(","));
        System.out.println(str);
    }

    @Test
    public void test9() {
        DoubleSummaryStatistics dss = emps.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(dss.getMax());
    }

    // partition
    @Test
    public void test8() {
        Map<Boolean, List<Employee>> map = emps.stream()
                .collect(Collectors.partitioningBy((e) -> e.getSalary() > 8000));
        System.out.println(map);
    }

    // Multilevel grouping
    @Test
    public void test7() {
        Map<Employee.Status, Map<String, List<Employee>>> mapMap = emps.stream()
                .collect(Collectors.groupingBy(Employee::getStatus, Collectors.groupingBy((e) -> {
                    if (e.getAge() < 30) {
                        return "youth";
                    } else if (e.getAge() <= 50) {
                        return "middle age";
                    } else {
                        return "old age";
                    }
                })));
        System.out.println(mapMap);
    }

    // grouping
    @Test
    public void test6() {
        Map<Employee.Status, List<Employee>> map = emps.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        System.out.println(map);
    }

    @Test
    public void test5() {
        // total
        Long count = emps.stream()
                .collect(Collectors.counting());
        System.out.println(count);
        // average value
        Double avage = emps.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avage);
        // the sum
        Double sum = emps.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);
        // Maximum
        Optional<Double> max = emps.stream()
                .map(Employee::getSalary)
                .collect(Collectors.maxBy((e1, e2) -> Double.compare(e1, e2)));
        System.out.println(max.get());
        // minimum value
        Optional<Double> min = emps.stream()
                .map(Employee::getSalary)
                .collect(Collectors.minBy(Double::compareTo));
        System.out.println(min);
    }

    @Test
    public void test4() {
        List<String> list = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        list.forEach(System.out::println);
        System.out.println(list.toString());

        HashSet<String> collect = emps.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));
        collect.forEach(System.out::println);
    }

Posted by GreenUser on Fri, 26 Nov 2021 00:06:12 -0800