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


概念
Stream是数据渠道,用于操作数据源(集合&数组)所生成的元素序列
Stream和Collection 集合之间的区别:**Collection是一种静态的内存数据结构,讲的数据,而Stream是有关计算的,讲的是计算。**前者主要面向内存,存储在内存当中,后者主要面向CPU,通过CPU实现计算。
注意:
-
Stream不会自己存储元素
-
不会改变源对象,相反会返回一个持有结果的新Stream
-
Stream操作是延时执行的。意味着他们会等到需要结果的时候才执行。一旦执行终止操作,就执行中间操作链,并产生结果。
-
Stream一旦执行了终止操作,就不能执行其他中间操作或者终止操作
执行流程:
-
实例化
-
一系列中间操作
-
执行终止操作

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}