What's new in Java 8 - Stream

Stream stream

Three operation steps of Stream

  • Create Stream
  • Intermediate operation
  • Terminate operation (terminal operation)

Create Stream

Four ways to create a stream

  • The stream() method or parallelStream() provided through the Collection series Collection
		List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();
		Stream<String> stream2 = list.parallelStream();
  • Get an array stream through a static method
		Employee[] employees = new Employee[10];
        Stream<Employee> stream2 = Arrays.stream(employees);
  • Through the of method in the static class of Stream class
		Stream<String> stream3 = Stream.of("aa","bb","cc","dd");
  • Create infinite flow: two (iteration and generation)
		// 4.1 iteration: pass a starting value and a unary operation
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);
        ///Intermediate operation termination operation
        stream4.limit(10).forEach(System.out::println);

        // 4.2 generation (infinite generation of random numbers)
        Stream.generate(()->Math.random()).forEach(System.out::println);

Intermediate operation

Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation"

1. Screening and slicing

methoddescribe
filterReceive Lambda and exclude some elements from the stream
limitTruncate the flow so that its elements do not exceed the given number
skip(n)Skip elements and return a stream that discards the first n elements. If there are less than n elements in the stream, an empty stream is returned, which is complementary to limit(n)
distinctFilter and remove duplicate elements through hashCode() and equals() of the elements generated by the flow

example:

  • Employee object
@Data
@NoArgsConstructor
@AllArgsConstructor
@EqualsAndHashCode()
public class Employee {

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

    public enum Status {
        BUSY,FREE,VOCATION;
    }

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

1.1 filter: filter

	List<Employee> employees = Arrays.asList(
            new Employee(1, "Zhang San", 18, 1111.11),
            new Employee(2, "Li Si", 49, 2222.22),
            new Employee(3, "Zhao Liu", 57, 3333.33),
            new Employee(4, "pseudo-ginseng", 35, 4444.44),
            new Employee(4, "pseudo-ginseng", 35, 4444.44)
    );	

    /**
     * Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation"
     * 1.Filtering and slicing: filter
     */
	@Test
    public void test1() {
        // Internal iteration: the iteration operation is completed by the Stream API
        employees.stream()
                .filter(e -> e.getAge() > 35)
                .forEach(System.out::println);

        // External iteration
        Iterator<Employee> it = employees.iterator();

        while (it.hasNext()) {
            System.out.println(it.next());
        }
    }

1.2 limit: interception

package cn.luis.stream.intermediate;

import cn.luis.stream.Employee;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.Iterator;
import java.util.List;

public class LimitTest {

    List<Employee> employees = Arrays.asList(
            new Employee(1, "Zhang San", 18, 1111.11),
            new Employee(3, "Zhao Liu", 57, 3333.33),
            new Employee(4, "pseudo-ginseng", 35, 4444.44),
            new Employee(2, "Li Si", 49, 2222.22),
            new Employee(5, "pseudo-ginseng", 35, 4444.44)
    );

    /**
     * Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation"
     * 2.Filtering and slicing: limit
     */
    @Test
    public void test2() {
        // limit; Short circuit, find two matching and terminate
        employees.stream()
                .filter(e -> {
                    //System.out.println("unqualified or directly discarded!"+ e);
                    return e.getAge() > 20;
                })
                .limit(2)
                .forEach(System.out::println);
    }

}

1.3 skip: skip

package cn.luis.stream.intermediate.shanxuanqiepian;

import cn.luis.stream.common.Employee;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;

public class SkipTest {

    List<Employee> employees = Arrays.asList(
            new Employee(1, "Zhang San", 18, 1111.11),
            new Employee(2, "Li Si", 49, 2222.22),
            new Employee(3, "Zhao Liu", 57, 3333.33),
            new Employee(4, "pseudo-ginseng", 35, 4444.44),
            new Employee(5, "pseudo-ginseng", 35, 4444.44)
    );

    /**
     * Intermediate operation: no operation will be performed, termination operation: all contents will be performed at one time, i.e. "lazy evaluation"
     * 1.Filtering and slicing: skip
     */
    @Test
    public void test3() {
        // limit; Skip the first two
        employees.stream()
                .filter(e -> e.getAge() > 18)
                .skip(2)
                .forEach(System.out::println);
    }
}

1.4 distinct: weight removal

package cn.luis.stream.intermediate.shanxuanqiepian;

import cn.luis.stream.common.Employee;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;

public class DistinctTest {

    List<Employee> employees = Arrays.asList(
            new Employee(1, "Zhang San", 18, 1111.11),
            new Employee(2, "Li Si", 49, 2222.22),
            new Employee(3, "Zhao Liu", 57, 3333.33),
            new Employee(4, "pseudo-ginseng", 35, 4444.44),
            new Employee(5, "pseudo-ginseng", 35, 4444.44)
    );

    /**
     * Filter and slice: distinct: filter to remove duplicate elements through hashCode() and equals() of the elements generated by the stream
     */
    @Test
    public void test4() {
        // distinct; De duplication [employees to rewrite hashcode and equals]
        employees.stream()
                .filter(e -> {
                    return e.getAge() > 25;
                })
                .distinct()
                .forEach(System.out::println);
    }

}

2. Mapping

The Function interface is passed into the map, and a parameter is passed in to return a value

methoddescribe
mapReceive lambda, convert elements into other forms or extract information, and receive a function as a parameter. The function will be applied to each element and mapped into a new element.
flatMapReceive a function as a parameter, replace each value in the stream with another stream, and then connect all streams into one stream

example:

package cn.luis.stream.intermediate.yingshe;

import org.junit.jupiter.api.Test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class MapTest {

    List<String> list = Arrays.asList("aaa", "bbb", "ccc", "ddd");

    /**
     * map
     */
    @Test
    public void test1() {
        list.stream()
                .map(s -> s.toUpperCase())
                .forEach(System.out::println);

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


        // This type of dolls can be replaced by flatMap (see test2)
        Stream<Stream<Character>> stream = list.stream().map(MapTest::filterCharacter);
        stream.forEach(sm -> {
            sm.forEach(System.out::println);
        });
    }

    /**
     * flatMap: Flattened map
     */
    @Test
    public void test2() {
        // Flattening map: originally, the stream was put into the map stream, but now the elements in the stream are directly put into the flatmap stream
        // Put {a,a,a},{b,b,b} Converted to {a, a, a, B, B, C, C, C}
        Stream<Character> characterStream = list.stream()
                .flatMap(MapTest::filterCharacter);

        characterStream.forEach(System.out::println);
    }

    /**
     * Split string
     * @param str
     * @return
     */
    public static Stream<Character> filterCharacter(String str) {
        List<Character> list = new ArrayList<>();
        for (Character ch : str.toCharArray()) {
            list.add(ch);
        }
        return list.stream();
    }
    
}

3. Sorting

methoddescribe
sorted()Natural sorting (Comparable)
sorted(Comparator com)Custom sort (Comparator)

example:

package cn.luis.stream.intermediate.sort;

import cn.luis.stream.common.Employee;
import org.junit.jupiter.api.Test;

import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class SortedTest {

    List<Employee> employees = Arrays.asList(
            new Employee(1, "Zhang San", 18, 1111.11),
            new Employee(2, "Li Si", 49, 2222.22),
            new Employee(3, "Zhao Liu", 57, 3333.33),
            new Employee(4, "pseudo-ginseng", 35, 4444.44),
            new Employee(5, "pseudo-ginseng", 35, 4444.44)
    );

    /**
     * 3. sort
     * sorted() -- Natural sorting (Comparable)
     * sorted(Comparator) -- Custom sort (Comparator)
     */
    @Test
    public void test1() {

        // Natural sorting ba
        Stream<Employee> sorted = employees.stream().sorted();

        // Sort by age, same age, sort by name
        employees.stream()
                .sorted((e1, e2) -> {
                    if (e1.getAge() == e2.getAge()) {
                        return e1.getName().compareTo(e2.getName());
                    } else {
                        Integer x = e1.getAge();
                        return x.compareTo(e2.getAge());
                    }
                }).forEach(System.out::println);
    }

}

Terminate operation

1. Find and match

methoddescribe
allMatchCheck that all elements match
anyMatchCheck to see if at least one element matches
noneMatchCheck if not all elements match
findFirstReturns the first element
findAnyReturns any element in the current stream
countReturns the total number of elements in the stream
maxReturns the maximum value in the stream
minReturns the minimum value in the stream

example:

  • Find objects
List<Employee> employees = Arrays.asList(
            new Employee(1, "Zhang San", 18, 1111.11, Status.BUSY),
            new Employee(2, "Li Si", 49, 2222.22, Status.FREE),
            new Employee(3, "Zhao Liu", 57, 3333.33, Status.BUSY),
            new Employee(4, "pseudo-ginseng", 35, 4444.44, Status.VOCATION),
            new Employee(2, "Li Shishi", 49, 2222.22, Status.FREE),
            new Employee(2, "Li Shishi", 49, 2222.22, Status.FREE),
            new Employee(2, "Li Shishi", 49, 2222.22, Status.FREE)
    );

1.1 match: Match

	@Test
    public void matchTest() {

        // Check that all elements match
        boolean b = employees.stream()
                .allMatch(e -> Employee.Status.BUSY.equals(e.getStatus()));
        System.out.println(b);

        // Check to see if at least one element matches
        boolean b2 = employees.stream()
                .anyMatch(e -> Employee.Status.BUSY.equals(e.getStatus()));
        System.out.println(b2);

        // Check if not all elements match
        boolean b3 = employees.stream()
                .noneMatch(e -> Employee.Status.BUSY.equals(e.getStatus()));
        System.out.println(b3);
    }

1.2 find: find

	@Test
    public void findTest() {

        // Returns the first element
        Optional<Employee> first = employees.stream()
                .sorted(Comparator.comparingDouble(Employee::getSalary))
                .findFirst();
        System.out.println(first.get());

        // Returns any element in the current stream
        Optional<Employee> any = employees.stream()
                .filter(e -> Employee.Status.FREE.equals(e.getStatus()))
                .findAny();
        System.out.println(any.get());

        // [parallel] returns any element in the current stream
        Optional<Employee> any2 = employees.parallelStream()
                .filter(e -> Employee.Status.FREE.equals(e.getStatus()))
                .findAny();
        System.out.println(any2.get());
    }

1.3 maximum value

	@Test
    public void numTest() {

        // Returns the total number of elements in the stream
        long count = employees.stream()
                .count();
        System.out.println(count);

        // Returns the maximum value in the stream
        Optional<Employee> max = employees.stream()
                .max(Comparator.comparingDouble(Employee::getAge));
        System.out.println(max.get());

        // Returns the minimum value in the stream
        Optional<Double> min = employees.stream()
                .map(Employee::getSalary)
                .min(Double::compare);
        System.out.println(min.get());
    }

2. Statute

methoddescribe
reduceYou can combine the elements in the flow repeatedly to get a value
  • Prepare data
public class EmpData {

    public static List<Employee> findAllEmployee() {
        return Arrays.asList(
                new Employee(1, "Zhang San", 18, 1111.11, Employee.Status.BUSY),
                new Employee(2, "Li Si", 49, 2222.22, Employee.Status.FREE),
                new Employee(3, "Zhao Liu", 57, 3333.33, Employee.Status.BUSY),
                new Employee(4, "pseudo-ginseng", 35, 4444.44, Employee.Status.VOCATION),
                new Employee(2, "Li Shishi", 49, 2222.22, Employee.Status.FREE),
                new Employee(2, "Li Shishi", 49, 2222.22, Employee.Status.FREE),
                new Employee(2, "Li Shishi", 49, 2222.22, Employee.Status.FREE)
        );
    }
}
  • example:
/**
 * Statute
 */
public class ReduceTest {

    List<Employee> employees = EmpData.findAllEmployee();

    /**
     * reduce(Starting value, binary operation): Protocol
     */
    @Test
    public void test3() {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5);

        Integer a = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(a);

        Integer b = list.stream()
                .reduce(0, Integer::sum);
        System.out.println(b);

        // Optimized writing method (map reduce mode)
        Optional<Integer> c = list.stream()
                .reduce(Integer::sum);
        System.out.println(c.get());

        // Optimized writing method (map reduce mode) + orElse
        Integer d = list.stream()
                .reduce(Integer::sum).orElse(0);
        System.out.println(d);
    }

}

3. Collection

Including set, calculation, grouping and partition

methoddescribe
collectConvert the Stream into other forms and receive the implementation of a Collectot interface, which is used to summarize the elements in the Stream

3.1 assembly

	@Test
    public void test4() {
        List<String> nameList = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());

        nameList.forEach(System.out::println);

        System.out.println("-----------Filter duplicate data--------------");
        Set<String> nameSet = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toSet());

        nameSet.forEach(System.out::println);

        System.out.println("-----------Drop to other collection types--------------");
        HashSet<String> nameHashSet = employees.stream()
                .map(Employee::getName)
                .collect(Collectors.toCollection(HashSet::new));

        nameHashSet.forEach(System.out::println);
    }

3.2 calculation

	@Test
    public void test5() {
        // total
        Long collect = employees.stream()
                .collect(Collectors.counting());
        System.out.println(collect);

        // average value
        Double avg = employees.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);

        // Maximum
        Optional<Double> max = employees.stream()
                .map(Employee::getSalary)
                .collect(Collectors.maxBy(Double::compare));
        System.out.println(max.get());

        // minimum value
        Optional<Double> min = employees.stream()
                .map(Employee::getSalary)
                .collect(Collectors.minBy(Double::compare));
        System.out.println(min.get());

        // the sum
        Double sum = employees.stream()
                .collect(Collectors.summingDouble(Employee::getSalary));
        System.out.println(sum);

        // Double: powerful computing
        DoubleSummaryStatistics salary = employees.stream()
                .collect(Collectors.summarizingDouble(Employee::getSalary));
        System.out.println(salary.getAverage());
        System.out.println(salary.getMax());
        System.out.println(salary.getCount());
    }

3.3 grouping and zoning

  • partition
	List<Employee> employees = EmpData.findAllEmployee();

    /**
     * collect Grouping of
     */
    @Test
    public void groupTest1() {
        // grouping
        Map<Employee.Status, List<Employee>> statusListMap = employees.stream()
                .collect(Collectors.groupingBy(Employee::getStatus));
        statusListMap.keySet().forEach(System.out::println);
        statusListMap.entrySet().forEach(System.out::println);
        System.out.println(statusListMap);

    }

    /**
     * collect Grouping of
     */
    @Test
    public void groupTest2() {
        // Multilevel grouping
        Map<String, List<Employee>> emMap = employees.stream()
                .collect(Collectors.groupingBy((employee) -> {
                    if (employee.getAge() <= 35) {
                        return "youth";
                    } else if (employee.getAge() > 20) {
                        return "old age";
                    } else {
                        return "juvenile";
                    }
                }));

        // View grouping (first method)
        emMap.keySet().forEach(key -> {
            System.out.println("======" + key + "======");
            emMap.get(key).forEach(System.out::println);
        });

        // View grouping (second way)
        emMap.forEach((k, v) -> {
            System.out.println("======" + k + "======");
            v.forEach(map -> {
                System.out.println(map);
            });
        });
    }

  • result:
======youth======
Employee(id=1, name=Zhang San, age=18, salary=1111.11, status=BUSY)
Employee(id=4, name=pseudo-ginseng, age=35, salary=4444.44, status=VOCATION)
======old age======
Employee(id=2, name=Li Si, age=49, salary=2222.22, status=FREE)
Employee(id=3, name=Zhao Liu, age=57, salary=3333.33, status=BUSY)
Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)
Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)
Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)

  • grouping
	/**
     * collect Partition of
     */
    @Test
    public void area1() {

        // Zoning: a zone is divided into those that meet the conditions and those that do not meet the conditions
        Map<Boolean, List<Employee>> emMap = employees.stream()
                .collect(Collectors.partitioningBy(e -> e.getSalary() > 2000.0));

        // View grouping (second way)
        emMap.forEach((k, v) -> {
            System.out.println("======" + k + "======");
            v.forEach(map -> {
                System.out.println(map);
            });
        });
    }
  • result
======false======
Employee(id=1, name=Zhang San, age=18, salary=1111.11, status=BUSY)
======true======
Employee(id=2, name=Li Si, age=49, salary=2222.22, status=FREE)
Employee(id=3, name=Zhao Liu, age=57, salary=3333.33, status=BUSY)
Employee(id=4, name=pseudo-ginseng, age=35, salary=4444.44, status=VOCATION)
Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)
Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)
Employee(id=2, name=Li Shishi, age=49, salary=2222.22, status=FREE)

Keywords: stream

Added by mraiur on Tue, 01 Feb 2022 22:47:05 +0200