Stream流学习总结

shucStream流是在后续学习当中使用很多的一个"工具",需要重点学习。

概念

Stream是数据渠道,用于操作数据源(集合&数组)所生成的元素序列

Stream和Collection 集合之间的区别:**Collection是一种静态的内存数据结构,讲的数据,而Stream是有关计算的,讲的是计算。**前者主要面向内存,存储在内存当中,后者主要面向CPU,通过CPU实现计算。

注意:

  1. Stream不会自己存储元素

  2. 不会改变源对象,相反会返回一个持有结果的新Stream

  3. Stream操作是延时执行的。意味着他们会等到需要结果的时候才执行。一旦执行终止操作,就执行中间操作链,并产生结果。

  4. Stream一旦执行了终止操作,就不能执行其他中间操作或者终止操作

执行流程:

  1. 实例化

  2. 一系列中间操作

  3. 执行终止操作

java 复制代码
package data;

import java.util.ArrayList;
import java.util.List;

public class EmployeeData {
    private  static List<Employee> list;

    public static List<Employee> getEmploees() {
        ArrayList<Employee> list = new ArrayList<>();
        list.add(new Employee(1001,"mahuateng",34,6000.38));
        list.add(new Employee(1002,"mayun",55,600000.38));
        list.add(new Employee(1003,"liuqiangdong",33,7000.38));
        list.add(new Employee(1004,"leijun",56,63000.38));
        list.add(new Employee(1005,"liyanhong",65,776000.38));
        list.add(new Employee(1006,"biergaici",67,60567500.38));
        list.add(new Employee(1007,"renzhengfei",67,6056500.38));
        list.add(new Employee(1001,"zhakeboge",32,6003453550.38));
       EmployeeData.list=list;
        return EmployeeData.list;
    }

}

创建Stream流(实例化)

重点需要下列代码的前两个方式

java 复制代码
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.stream.Stream;

public class Main {
    public static void main(String[] args) {
        //创建stream方式1:通过集合(collection当中自带的stream方法)
        //获取顺序流
        List<Integer> list = new ArrayList<>();
        Stream<Integer> stream = list.stream();//按元素顺序进行判断
        //获取并行流
        Stream<Integer> integerStream = list.parallelStream();

        //创建Stream方式2:使用数组
        //调用Arrays
        Integer[] arr = {1, 2, 3, 4, 5};
        Stream<Integer> stream1 = Arrays.stream(arr);//stream本身并不存储数据,只能用于操作数据

        //创建Stream方式3:通过Stream的of()方法
        Stream<String> stream2 = Stream.of("AA", "BB", "SS", "DD");
        


    }
}

中间操作

筛选&切片:

映射:

排序

过滤&切片

javascript 复制代码
import data.Employee;
import data.EmployeeData;

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

public class Main {
    public static void main(String[] args) {
        //查询员工表当中薪资大于7000的员工信息
        List<Employee> list = EmployeeData.getEmploees();
        Stream<Employee> stream = list.stream();//获取流
        stream.//过滤
                filter(employee -> employee.getSalary() > 7000)//要输出:需要终止操作,同时需要种植操作才能执行终止操作
                //forEach:遍历,进行打印(使用函数引用)
                .forEach(System.out::println);
        System.out.println("____________limit__________");
        //limit(n)截断流,使元素不超过指定数量,注意这里不能继续使用上面的stream进行截断操作(已经被终止操作,无法执行中间操作)
        Stream<Employee> stream1 = list.stream();//获取新的stream流
        //获取前n个数据
        stream1.limit(4).forEach(System.out::println);
        //两个操作可以进行组合(方法链)
        System.out.println("____________filter+limit___");
        Stream<Employee> stream2 = list.stream();
        stream2.filter(emp -> emp.getSalary() > 70000).limit(4).forEach(System.out::println);
        System.out.println("____________skip___________");
        //跳过元素,返回一个扔掉前n个元素的流。流中元素不足n个,返回空流
        list.stream().skip(5).forEach(System.out::println);
        System.out.println("____________distinct_______");
        //distinct:筛选,通过流所生成元素的hashCode()和equals()去重(需要Employee类重写对应方法)
        list.add(new Employee(1009,"musk",40,9003453550.38));
        list.add(new Employee(1009,"musk",40,9003453550.38));
        list.add(new Employee(1009,"musk",40,9003453550.38));
        list.add(new Employee(1009,"musk",40,9003453550.38));
        list.add(new Employee(1009,"musk",40,9003453550.38));
        list.stream().distinct().forEach(System.out::println);

    }
}

输出:

java 复制代码
输出:
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
Employee{id=1008, name='zhakeboge', age=32, salary=6.00345355038E9}
____________limit__________
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
____________filter+limit___
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
____________skip___________
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
Employee{id=1008, name='zhakeboge', age=32, salary=6.00345355038E9}
____________distinct_______
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
Employee{id=1008, name='zhakeboge', age=32, salary=6.00345355038E9}
Employee{id=1009, name='musk', age=40, salary=9.00345355038E9}

映射

java 复制代码
public class Main {
    public static void main(String[] args) {
        //map(Function f):接受一个函数作为承诺书,将元素转换为其他形式/提取信息,韩式应用到每个元素上)
        List<String> list = Arrays.asList("aa", "bb", "cc", "dd");
        //转换大小写
        list.stream().
                map(str->str.toUpperCase()).forEach(System.out::println);
        //或者写成方法引用形式:map(String::toUpperCase)
        System.out.println("_______________________________");
        //获取员工姓名长度大于5的员工姓名
        EmployeeData.getEmploees().stream().filter( emp->emp.getName().length()>5)
                .map(emp->emp.getName())
                .forEach(System.out::println);
        
    }
}

输出:

java 复制代码
输出:
AA
BB
CC
DD
_______________________________
mahuateng
liuqiangdong
leijun
liyanhong
biergaici
renzhengfei
zhakeboge

排序

java 复制代码
 public static void main(String[] args) {
       //sorted自然升序排序
        //但是注意:本身顺序没变
        Integer[] arr = {23324, 12124, 45, 123, 4567, 45, 5661, 3, 5, 7, 9};
        String[] arr1 = {"GG", "AA", "WW", "NN", "SS", "JJ"};
        Arrays.stream(arr).sorted().forEach(System.out::println);
        Arrays.stream(arr1).sorted().forEach(System.out::println);
        //自定义类实现comparable才能正常使用
//        EmployeeData.getEmployees().stream().sorted().forEach(System.out::println);
        System.out.println("___________________________________");
        //定制排序
        //按照年龄进行升序排序
        /*正常写法:新建comparator
        * .sorted(new Comparator<Employee>() {
            @Override
            public int compare(Employee o1, Employee o2) {
                return o1.getAge()-o2.getAge()
            }
        })
        * */
        EmployeeData.getEmployees().stream().sorted((e1,e2)->e1.getAge()-e2.getAge()).forEach(System.out::println);

    }

输出:

java 复制代码
输出:
3
5
7
9
45
45
123
4567
5661
12124
23324
AA
GG
JJ
NN
SS
WW
___________________________________
Employee{id=1008, name='zhakeboge', age=32, salary=6.00345355038E9}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}

终止操作

  • 终端操作会从流的流水线生成结果。结果可以是任何不是流的值,例如:List、Integer、甚至是void

  • 流进行终止操作之后不能再使用

匹配与查找

java 复制代码
import data.Employee;
import data.EmployeeData;

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

public class Main {
    public static void main(String[] args) {
        //allMatch
        //是否所有员工年龄都大于18
        System.out.println(EmployeeData.getEmployees().stream().allMatch(emp -> emp.getAge() > 18));
        System.out.println("___________________________________");
        //anyMatch
        //至少有一个匹配(是否存在)
        System.out.println(EmployeeData.getEmployees().stream().anyMatch(emp -> emp.getAge() > 18));
        System.out.println("___________________________________");
        //findFirst:返回第一个元素,返回结果是一个Optional,使用get方法拿到对应对象
        System.out.println(EmployeeData.getEmployees().stream().findFirst());
        System.out.println(EmployeeData.getEmployees().stream().findFirst().get());
        System.out.println("___________________________________");
        //求个数
        System.out.println(EmployeeData.getEmployees().stream().count());
        System.out.println("___________________________________");
        //max(Comparator c)返回流当中最大值
        //返回最大工资的员工
        //使用三元运算符,1表示大,-1表示小,注意不能写0!比较器当中0表示两者相等
        System.out.println(EmployeeData.getEmployees().stream().max((e1, e2) -> e1.getSalary() > e2.getSalary() ? 1 : -1));
        System.out.println(EmployeeData.getEmployees().stream().max((e1, e2) ->Double.compare(e1.getSalary(),e2.getSalary())));
        System.out.println("___________________________________");
        //得到工资最多员工工资
        //方法1:get方法得到对象之后使用对应getter方法
        System.out.println(EmployeeData.getEmployees().stream().max((e1, e2) ->Double.compare(e1.getSalary(),e2.getSalary())).get().getSalary());
        //map映射先拿到工资之后进行比较;同样可以使用方法引用:Double::compare
        System.out.println(EmployeeData.getEmployees().stream().map(emp->emp.getSalary()).max((s1,s2)->Double.compare(s1,s2)));
        System.out.println("___________________________________");
        //类似的min
        System.out.println(EmployeeData.getEmployees().stream().min((e1, e2) ->Double.compare(e1.getSalary(),e2.getSalary())));
        System.out.println("___________________________________");
        //forEach进行遍历
        //最简单的:进行打印
        EmployeeData.getEmployees().stream().forEach(System.out::println);
        System.out.println("jdk8当中增加了list对应的遍历方法");
        EmployeeData.getEmployees().forEach(System.out::println);
        
    }
}

输出:

java 复制代码
输出 
true
___________________________________
true
___________________________________
Optional[Employee{id=1001, name='mahuateng', age=34, salary=6000.38}]
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
___________________________________
8
___________________________________
Optional[Employee{id=1008, name='zhakeboge', age=32, salary=6.345355038E7}]
Optional[Employee{id=1008, name='zhakeboge', age=32, salary=6.345355038E7}]
___________________________________
6.345355038E7
Optional[6.345355038E7]
___________________________________
Optional[Employee{id=1001, name='mahuateng', age=34, salary=6000.38}]
___________________________________
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
Employee{id=1008, name='zhakeboge', age=32, salary=6.345355038E7}
jdk8当中增加了list对应的遍历方法
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
Employee{id=1008, name='zhakeboge', age=32, salary=6.345355038E7}

归约

javascript 复制代码
import data.Employee;
import data.EmployeeData;

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

public class Main {
    public static void main(String[] args) {
        //reduce(T identity ,BinaryOperator):可以将流当中元素反复结合起来,得到一个值
        //计算自然数1-10之和
        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
        List<Employee> listEm = EmployeeData.getEmployees();
        //identity:种子值(初始值)
        System.out.println(list.stream().reduce(0, (x, y) -> x + y));
        //使用Integer的sum方法
        System.out.println(list.stream().reduce(0, (x, y) -> Integer.sum(x,y)));
        //sum进阶:使用方法引用
        System.out.println(list.stream().reduce(0, Integer::sum));
        System.out.println("____________________________");
        //reduce(BinaryOperator):可以将流当中元素反复结合起来,得到一个值,返回Optional<T>
        //计算公司所有员工工资之和
        System.out.println(listEm.stream().map(e -> e.getSalary()).reduce( Double::sum).get());
        System.out.println("____________________________");
    }
}

输出:

java 复制代码
输出 
55
55
55
____________________________
1.3152955303999999E8
____________________________

收集

常用方法:

java 复制代码
public static void main(String[] args) {
    List<Employee> listEm = EmployeeData.getEmployees();
    //collect(Collector c)将流转换成其他类顶
    //查找工资大于1000000的员工并返回一个list作为结果
    ArrayList<Employee> list1 = listEm.stream().filter(e -> e.getSalary() > 1000000).collect(Collectors.toCollection(ArrayList::new));
    list1.forEach(System.out::println);
    System.out.println("____________________________");
    //按照员工年龄进行排序返回到一个list当中
    List<Employee> list2 = listEm.stream().sorted((e1, e2) -> e1.getAge() - e2.getAge()).collect(Collectors.toList());
    list2.forEach(System.out::println);
}

输出:

java 复制代码
输出 
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
Employee{id=1008, name='zhakeboge', age=32, salary=6.345355038E7}
____________________________
Employee{id=1008, name='zhakeboge', age=32, salary=6.345355038E7}
Employee{id=1003, name='liuqiangdong', age=33, salary=7000.38}
Employee{id=1001, name='mahuateng', age=34, salary=6000.38}
Employee{id=1002, name='mayun', age=55, salary=600000.38}
Employee{id=1004, name='leijun', age=56, salary=63000.38}
Employee{id=1005, name='liyanhong', age=65, salary=776000.38}
Employee{id=1006, name='biergaici', age=67, salary=6.056750038E7}
Employee{id=1007, name='renzhengfei', age=67, salary=6056500.38}
相关推荐
⑩-2 小时前
基于Redis Lua脚本的秒杀系统
java·redis
0和1的舞者2 小时前
《网络编程核心概念与 UDP Socket 组件深度解析》
java·开发语言·网络·计算机网络·udp·socket
稚辉君.MCA_P8_Java2 小时前
Gemini永久会员 Java动态规划
java·数据结构·leetcode·排序算法·动态规划
oioihoii2 小时前
C++语言演进之路:从“C with Classes”到现代编程基石
java·c语言·c++
N***73853 小时前
SQL锁机制
java·数据库·sql
Java天梯之路3 小时前
Java 初学者必看:接口 vs 抽象类,到底有什么区别?
java·开发语言
小熊officer3 小时前
Nginx中正向代理,反向代理,负载均衡
java·nginx·负载均衡
信码由缰3 小时前
Java 应用容器化与部署
java
方白羽3 小时前
Kotlin遇上Java 静态方法
android·java·kotlin