Java基础,Stream的用法

原创
2019/12/23 23:06
阅读数 126
Stream是数据渠道,用于操作集合、数组等。
集合讲的是数据,Stream讲的是计算,即Stream是对集合的一系列操作过程。

注意:
1、Stream不会自己存储元素
2、Stream不会改变源对象,它会返回一个持有操作结果的新Stream
3、Stream操作是延迟执行的,这意味着他们会等到需要结果的时候才执行

Employee实体类,后面会用到

package com.lee.jdk.Entity;

import java.util.Objects;

public class Employee {

    private Integer id;

    private String name;

    private int age;

    private Double salary;

    private Status status;

    public Employee() {
    }

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

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

    public Employee(Integer id, String name, int age, Double salary, Status status) {
        this.id = id;
        this.name = name;
        this.age = age;
        this.salary = salary;
        this.status = status;
    }

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

    public Integer getId() {
        return id;
    }

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

    public String getName() {
        return name;
    }

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

    public int getAge() {
        return age;
    }

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

    public Double getSalary() {
        return salary;
    }

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

    public Status getStatus() {
        return status;
    }

    public void setStatus(Status status) {
        this.status = status;
    }

    public enum Status{
        FREE,BUSY,VACATION
    }

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

    @Override
    public boolean equals(Object o) {
        if (this == o) return true;
        if (o == null || getClass() != o.getClass()) return false;
        Employee employee = (Employee) o;
        return age == employee.age &&
                Objects.equals(id, employee.id) &&
                Objects.equals(name, employee.name) &&
                Objects.equals(salary, employee.salary);
    }

    @Override
    public int hashCode() {
        return Objects.hash(id, name, age, salary);
    }
}

Stream语法规则 一

package com.lee.jdk.stream;

import com.lee.jdk.Entity.Employee;
import org.junit.Test;

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

/**
 * 一、Stream的三个操作步骤:
 * 1、创建Stream
 * 2、中间操作
 * 3、终止操作
 *
 * 二、创建Stream
 *    1、Collection
 *    2、Arrays
 *    3、Stream的of
 *    4、Stream的Iterate和Generate创建无限流
 *
 * 三、中间操作
 *    1、筛选 和 切片
 *          filter : 接受lambda,并排除某些元素
 *          limit :  截断流,使其元素不超过给定数量
 *          skip(n) : 跳过元素,返回一个扔掉了前N个元素的流。若流中元素不足N个,则返回一个空流。
 *          distinct : 筛选,通过流生成元素的hashCode和equals去除重复元素
 *    2、映射
 *          map:会将集合中的数据,一个个的应用于map的函数上
 *          flatMap : 会将集合中的数据,一个个的应用于map的函数上.并且将流中的每一个值换成另一个流,然后把所有流连成一个流
 *
 *    3、排序
 *          sorted 自然排序
 *          sorted(Comparator comp) 自定义排序
 */
public class TestStreamApi1 {

    List<Employee> employeeList = Arrays.asList(
            new Employee(1,"张三",25,17000d),
            new Employee(2,"李四",18,19000d),
            new Employee(3,"王五",55,7000d),
            new Employee(4,"赵六",39,12000d),
            new Employee(5,"刘七",28,14000d),
            new Employee(5,"刘七",28,14000d),
            new Employee(5,"刘七",28,14000d)
    );

    //1、四种创建Stream的方式
    @Test
    public void test1(){
        //1、通过Collection系列集合提供的串行Stream()和并行parallelStream()
        List<String> list = new ArrayList<>();
        Stream<String> stream1 = list.stream();

        //2、通过Arrays中的静态方法Stream()
        Employee[] emps = new Employee[10];
        Stream<Employee> stream2 = Arrays.stream(emps);

        //3、通过Stream类中的静态方法of()
        Stream<String> stream3 = Stream.of("aa","bb","cc");

        //4、Stream方法创建无限流
        Stream<Integer> stream4 = Stream.iterate(0, (x) -> x + 2);

        Stream<Double> stream5 = Stream.generate(() -> Math.random() * 100);
    }


    //2、中间操作--filter
    @Test
    public void test2(){
        //中间操作,不会执行任何操作---集合会在stream内部循环
        Stream<Employee> stream = employeeList.stream()
                .filter((e) -> {
                    System.out.println("中间操作,不会执行任何操作");
                    return e.getAge() > 35;
                });

        //终止操作:一次性执行全部内容,即 "惰性求值"
        stream.forEach(System.out::println);
    }

    //3、中间操作--limit
    @Test
    public void test3(){
        //中间操作,不会执行任何操作
        Stream<Employee> stream = employeeList.stream()
                .filter((e) -> {
                    System.out.println("中间操作,limit");
                    return e.getSalary()>8000;
                })
                .limit(2);//查找到Limit限定的值后,集合就中断不再继续执行了。这就是"短路"

        //终止操作:一次性执行全部内容,即 "惰性求值"
        stream.forEach(System.out::println);
    }

    //4、中间操作--skip
    @Test
    public void test4(){
        //中间操作,不会执行任何操作
        Stream<Employee> stream = employeeList.stream()
                .filter((e) -> e.getSalary()>8000)
                .skip(2);//跳过前两个
        //终止操作:一次性执行全部内容,即 "惰性求值"
        stream.forEach(System.out::println);
    }

    //5、中间操作--distinct
    @Test
    public void test5(){
        //中间操作,不会执行任何操作
        Stream<Employee> stream = employeeList.stream()
                .filter((e) -> e.getSalary()>8000)
                .distinct();//去重必须重写Employee的hashcode和equals方法
        //终止操作:一次性执行全部内容,即 "惰性求值"
        stream.forEach(System.out::println);
    }

    //6、map:会将集合中的数据,一个个的应用于map的函数上
    @Test
    public void test6(){
        List<String> list = Arrays.asList("aaa","bbb","ccc","ddd","eee");
        list.stream()
                .map((s)->s.toUpperCase())
                .forEach(System.out::println);

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

        employeeList.stream()
                    .map((e)->e.getName()+"-  ")
                    .distinct()
                    .forEach(System.out::print);

    }

    //7、flatmap : 会将集合中的数据,一个个的应用于map的函数上.并且将流中的每一个值换成另一个流,然后把所有流连成一个流
    @Test
    public void test7(){
        List<String> list = Arrays.asList("aaa","bbb","ccc");
        //map---类似于list中的add
        Stream<Stream<Character>> mapStream = list.stream()
                                    .map(TestStreamApi1::filterCharacter);
        mapStream.forEach((sm)->sm.forEach(System.out::println));

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

        //flatMap---类似于list中的addAll
        Stream<Character> flatMapStream = list.stream()
                .flatMap(TestStreamApi1::filterCharacter);

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

    }

    public static Stream<Character> filterCharacter(String s){
        List<Character> list = new ArrayList<>();
        for(Character c : s.toCharArray()){
            list.add(c);
        }
        return list.stream();
    }

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

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

        employeeList.stream()
                .sorted((e1,e2)->{
                    if(Objects.equals(e1.getAge(),e2.getAge())){
                        return -e1.getSalary().compareTo(e2.getSalary());
                    }else{
                        return Integer.compare(e1.getAge(),e2.getAge());
                    }
                })
                .forEach(System.out::println);
    }

}

Stream语法规则 二

package com.lee.jdk.stream;

import com.lee.jdk.Entity.Employee;
import org.junit.Test;

import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 终止操作
 *      1、查找与匹配
 *          AllMatch  检查是否全部匹配
 *          anyMatch  检查是否至少匹配一个元素
 *          noneMatch 检查是否全部没匹配
 *
 *          findFirst  返回第一个元素
 *          findAny    返回任意元素
 *          count      返回流中元素总个数
 *          max        返回流中最大值
 *          min        返回流中最小值
 *
 *      2、规约
 *          reduce  将流中元素反复结合起来,得到一个值
 *      3、收集
 *          collect  将结果放入集合中
 */
public class TestStreamApi2 {

    List<Employee> employeeList = Arrays.asList(
            new Employee(1,"张三",25,17000d, Employee.Status.BUSY),
            new Employee(2,"李四",18,19000d, Employee.Status.VACATION),
            new Employee(3,"王五",55,7000d, Employee.Status.FREE),
            new Employee(4,"赵六",39,12000d, Employee.Status.BUSY),
            new Employee(5,"刘七",28,14000d, Employee.Status.FREE),
            new Employee(6,"刘七",28,15000d, Employee.Status.VACATION),
            new Employee(7,"刘七",28,16000d, Employee.Status.BUSY)
    );


    //1、查找与匹配
    @Test
    public void test(){
        //allMatch
        boolean b = employeeList.stream()
                .allMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b);

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

        //anyMatch
        boolean b1 = employeeList.stream()
                .anyMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b1);

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

        //noneMatch
        boolean b2 = employeeList.stream()
                .noneMatch((e) -> e.getStatus().equals(Employee.Status.BUSY));
        System.out.println(b2);

        System.out.println("----------------------------");
        
        //findFirst
        Optional<Employee> op1 = employeeList.stream()
                .sorted((e1, e2) -> Double.compare(e1.getSalary(), e2.getSalary()))
                .findFirst();
        System.out.println(op1.get());

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

        //findAny
        Optional<Employee> op2 = employeeList.stream()
                .filter((e)->e.getStatus().equals(Employee.Status.BUSY))
                .findAny();
        System.out.println(op2.get());

        Optional<Employee> op3 = employeeList.parallelStream()
                .filter((e)->e.getStatus().equals(Employee.Status.BUSY))
                .findAny();
        System.out.println(op3.get());

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

        //count
        long count = employeeList.stream()
                .count();
        System.out.println(count);

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

        //max
        Optional<Integer> op4 = employeeList.stream()
                .map(Employee::getAge)
                .max((e1, e2) -> Integer.compare(e1, e2));
        System.out.println(op4.get());

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

        //min
        Optional<Integer> op5 = employeeList.stream()
                .map(Employee::getAge)
                .min((e1, e2) -> Integer.compare(e1, e2));
        System.out.println(op5.get());


    }

    //2、规约:reduce  将流中元素反复结合起来得到一个值
    @Test
    public void test2(){

        //将1-10中所有数相加
        List<Integer> list = Arrays.asList(1,2,3,4,5,6,7,8,9,10);
        Integer num = list.stream()
                .reduce(0, (x, y) -> x + y);
        System.out.println(num);

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

        //所有人工资总和
        Optional<Double> op1 = employeeList.stream()
                .map(Employee::getSalary)
                .reduce(Double::sum);
        System.out.println(op1.get());

    }

    //3、收集
    @Test
    public void test3(){
        //收集所有人的姓名
        List<String> list = employeeList.stream()
                .map(Employee::getName)
                .collect(Collectors.toList());
        list.forEach(System.out::println);

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

        //收集BUSY状态的员工
        List<Employee> list2 = employeeList.stream()
                .filter((e) -> e.getStatus().equals(Employee.Status.BUSY))
                .collect(Collectors.toList());
        list2.forEach(System.out::println);

        //总数
        Long count = employeeList.stream()
                .collect(Collectors.counting());
        System.out.println(count);

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

        //总和
        Double sum = employeeList.stream()
                .collect(Collectors.summingDouble((e) -> e.getSalary()));
        System.out.println(sum);

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

        //平均值
        Double avg = employeeList.stream()
                .collect(Collectors.averagingDouble(Employee::getSalary));
        System.out.println(avg);

        //等等

    }

}

展开阅读全文
加载中
点击引领话题📣 发布并加入讨论🔥
打赏
0 评论
0 收藏
0
分享
返回顶部
顶部