stream流
体验stream流的作用
需求:按照下面的要求完成集合的创建和遍历
1 创建一个集合,存储多个字符串元素
2 把集合中所有以"张"开头的元素存储到一个新的集合
3 把 "张"开头的集合中的长度为3的元素存储到一个新的集合
4 遍历上一步得到的集合中的元素输出
List<String> list = new ArrayList<>();
list.add("张无忌");
list.add("周芷若");
list.add("赵敏");
list.add("张强");
list.add("张三丰");
不采用stream流
List<String> names = new ArrayList<>();
Collections.addAll(names,"张无忌","赵敏","周芷若","张强","张三丰");
System.out.println("原始names集合:"+names);
List<String> list1 = new ArrayList<>();
for (String name : names) {
if (name.startsWith("张")){
list1.add(name);
}
}
System.out.println("以张开头的集合:"+list1);
List<String> list2 = new ArrayList<>();
for (String s : list1) {
if (s.length() == 3){
list2.add(s);
}
}
System.out.println("以张开头并且长度为3的集合:"+list2);
原始names集合:[张无忌, 赵敏, 周芷若, 张强, 张三丰]
以张开头的集合:[张无忌, 张强, 张三丰]
以张开头并且长度为3的集合:[张无忌, 张三丰]
采用stream流
names.stream().filter(s->s.startsWith("张")).filter(s->s.length() == 3).forEach(s-> System.out.println(s));
stream流的思想
stream思想核心
1.先得到集合或者数组的stream流(相当于一根传送带)
2.把元素放上去
3.然后就用这个Stream流简化API来方便的操作元素
stream流的获取
stream的三类方法
- 获取stream
创建一条流水线,并把数据放到流水线上准备进行操作
- 中间方法
流水线上的操作.一次操作完毕之后,还可以继续进行其他操作
- 终结方法
一个stream流只能有一个终结方法,是流水线上的最后一个操作
集合获取stream的方式
可以使用Collection接口中的默认方法stream()生成流
名称 | 说明 |
---|---|
default Stream stream() | 获取当前集合对象的stream流 |
数组获取stream的方式
名称 | 说明 |
---|---|
public static Stream stream(T[] array) | 获取当前数组的stream流 |
public static Stream of(T … values) | 获取当前数组/可变数据的Stream流 |
/*
不同集合获取流的操作
*/
/*---------1.Collection集合获取流---------*/
Collection<String> list = new ArrayList<>();
Stream<String> listStream = list.stream();
/*---------2.Map集合获取流---------*/
Map<String,Integer> map = new HashMap<>();
//键流
Stream<String> keyStream = map.keySet().stream();
//值流
Stream<Integer> valueStream = map.values().stream();
//键值对流
Stream<Map.Entry<String,Integer>> keyAndValueStream = map.entrySet().stream();
/*---------3.数组获取流---------*/
String[] names = {"张三","李四","王五"};
Stream<String> arrayStream = Arrays.stream(names); // 第一种方式
Stream<String> arrayStream2 = Stream.of(names); //第二种方式
stream流常用API
Stream流的常见中间操作方法
方法名称 | 说明 |
---|---|
Stream filter(Predicate<? super T> predicate) | 用于对流中的数据进行过滤 |
Stream limit(long maxSize) | 获取前几个元素 |
Stream skip(long n) | 跳过前几个元素 |
Stream distinct() | 取出流中重复的元素,依赖(hashCode和equals方法) |
static Stream concat(Stream a,Stream b) | 合并a和b两个流为一个流 |
/**
* Strean流的常用API(中间操作方法)
*/
//filter 用来过滤
List<String> list = new ArrayList<>();
Collections.addAll(list,"张强强","陆小凤","张无忌","小花","刘明月","张小鹿","张无忌");
//list.stream().filter(s -> s.startsWith("张")).filter(s->s.length() == 3).forEach(s -> System.out.println(s));
// limit --->获取前几个元素 skip----> 跳过前几个元素
//list.stream().limit(4).skip(list.size() - 4).forEach(s -> System.out.println(s));
//distinct 去重流中重复的元素
//list.stream().distinct().forEach(s-> System.out.println(s));
//concat 合并a和b流为一个流
Stream<String> s1 = list.stream().filter(s->s.startsWith("张")); // 张强强 张无忌 张小鹿 张无忌
Stream<String> s2 = list.stream().skip(4); // 刘明月 张小鹿 张无忌
Stream<String> s3 = Stream.concat(s1,s2); //合并 s1和 s2 两个流
s3.filter(s -> s.startsWith("张")).distinct().forEach(s -> System.out.println(s)); // 张小鹿 张无忌 张强强
Map加工方法
第一个参数 : 原材料
第二个参数 : 加工后的结果
//Map加工方法 第一个参数: 加工的原材料 第二个参数: 加工后的结果
// 给所有元素的前面加上一个 : 武侠小说
list.stream().map(s -> "武侠小说" + s).forEach(s -> System.out.println(s));
/*
武侠小说张强强
武侠小说陆小凤
武侠小说张无忌
武侠小说小花
武侠小说刘明月
武侠小说张小鹿
武侠小说张无忌
*/
需求:把所有名称 都加工成一个学生对象
//需求 : 将所有名称加工成一个学生对象
list.stream().map(s->new Student(s)).forEach(s-> System.out.println(s));
注意
- 中间方法也称为 非终结方法,调用完成后返回新的Stream流可以继续使用,支持链式编程
- 在Stream流中无法直接修改集合,数组中的数据
Stream流的常见终结操作方法
名称 | 说明 |
---|---|
void forEach(Consumer action) | 对此流的每个元素执行遍历操作 |
long count() | 返回此流中的元素数 |
stream流的综合应用
案例
需求:
某个公司的开发部门,分为开发一部和二部,现在需要进行年中数据结算
分析:
1.员工信息至少包含了(姓名 性别 工资 奖金 处罚记录)
2.开发一部有4个员工,开发二部有5个员工
3.分别筛选出2个部门的最高工资的员工信息,封装成优秀员工对象Topperformer
4.分别统计出2各个部门的平均月收入,要求去掉最高和最低工资
5.统计2个开发部门整体的平均工资,去掉最低和最高工资的平均值
需求:
某个公司的开发部门,分为开发一部和二部,现在需要进行年中数据结算
分析:
1.员工信息至少包含了(姓名 性别 工资 奖金 处罚记录)
2.开发一部有4个员工,开发二部有5个员工
3.分别筛选出2个部门的最高工资的员工信息,封装成优秀员工对象Topperformer
4.分别统计出2各个部门的平均月收入,要求去掉最高和最低工资
5.统计2个开发部门整体的平均工资,去掉最低和最高工资的平均值
Employee类
package mystream;
public class Employee implements Comparable<Employee>{
private String name; //姓名
private String sex; //性别
private double salary; //工资
private double bunus; //奖金
private String punish; //处罚记录
public Employee() {
}
public Employee(String name, String sex, double salary, double bunus, String punish) {
this.name = name;
this.sex = sex;
this.salary = salary;
this.bunus = bunus;
this.punish = punish;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getSex() {
return sex;
}
public void setSex(String sex) {
this.sex = sex;
}
public double getSalary() {
return salary;
}
public void setSalary(double salary) {
this.salary = salary;
}
public double getBunus() {
return bunus;
}
public void setBunus(double bunus) {
this.bunus = bunus;
}
public String getPunish() {
return punish;
}
public void setPunish(String punish) {
this.punish = punish;
}
@Override
public String toString() {
return "Employee{" +
"name='" + name + '\'' +
", sex='" + sex + '\'' +
", salary=" + salary +
", bunus=" + bunus +
", punish='" + punish + '\'' +
'}';
}
@Override
public int compareTo(Employee o) {
return Double.compare(this.getSalary() + this.getBunus(),o.getSalary() + o.getBunus());
}
}
EmployeeTest类
package mystream;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.function.Predicate;
import java.util.stream.Stream;
public class TestEmployee {
public static double allmoney = 0;
public static double allmoney1 = 0;
public static void main(String[] args) {
// 开发一部
List<Employee> one = new ArrayList<>();
one.add(new Employee("孙悟空","男",15000,2000,"顶嘴,被打了"));
one.add(new Employee("猪八戒","男",35000,12000,null));
one.add(new Employee("沙僧","男",25000,5000,null));
one.add(new Employee("白骨精","女",10000,1000,null));
// 开发二部
List<Employee> two= new ArrayList<>();
two.add(new Employee("武松","男",65000,20000,null));
two.add(new Employee("武大郎","男",3000,12000,"被下毒"));
two.add(new Employee("西门庆","男",125000,50000,"被打"));
two.add(new Employee("潘金莲","女",110000,12000,"被骂"));
two.add(new Employee("李逵","男",10000,1000,null));
// 3.分别筛选出2个部门的最高工资的员工信息,封装成优秀员工对象Topperformer
// 开发一部 (二部一样的操作)
Employee e = one.stream().max((e1,e2)->Double.compare(e1.getBunus() + e1.getSalary() , e2.getSalary() + e2.getBunus())).get();
Topperformer t = new Topperformer(e.getName(),e.getPunish());
System.out.println(e);
System.out.println(t);
//4.分别统计出2各个部门的平均月收入,要求去掉最高和最低工资
//开发一部 (二部一样的操作)
one.stream().sorted((o1,o2)->Double.compare(o2.getSalary() + o2.getBunus(),o1.getSalary() + o1.getBunus()))
.skip(1).limit(one.size() - 2).forEach(s-> {
allmoney += s.getSalary() + s.getBunus();
});
System.out.println("开发一部的平均工资是:"+allmoney / 2);
//5.统计2个开发部门整体的平均工资,去掉最低和最高工资的平均值
Stream<Employee> em1 = one.stream();
Stream<Employee> em2 = one.stream();
Stream<Employee> em3 = Stream.concat(em1,em2);
em3.sorted((o1,o2)->Double.compare(o2.getSalary()+o2.getBunus(),o1.getSalary()+o1.getBunus())) //降序
.skip(1).limit(one.size() + two.size() - 2).forEach(s->{
allmoney1 += s.getSalary() + s.getBunus();
});
BigDecimal a = BigDecimal.valueOf(allmoney1);
BigDecimal b = BigDecimal.valueOf(one.size() + two.size() - 2);
System.out.println("开发一部和开发二部整体平均薪资为:"+a.divide(b,2, RoundingMode.HALF_UP));
}
}
收集stream流
收集Stream流的含义
把Stream流操作后的结果数据转回到集合或者数据中去
- Stream:方便操作集合/数组的手段
- 集合/数组: 目的
Stream流的收集方法
名称 | 说明 |
---|---|
R collect(Collector collector) | 开始收集Stream流,指定收集器 |
Collectors工具类提供具体的收集方法
名称 | 说明 |
---|---|
public static Collector toList() | 把元素收集到List集合中 |
public static Collector toSet() | 把元素收集到Set集合中 |
public static Collector toMap(Function keyMapper,Function valueMapper) | 把元素收集到Map集合中 |
List<String> list = new ArrayList<>();
Collections.addAll(list,"李四","张三","王五","张无忌","张强","赵敏","张三丰","张三丰");
Stream<String> s1 = list.stream().filter(s-> s.startsWith("张"));
// 将流转换成List集合 注意: 调用collect方法转换后的集合是可修改的
List<String> zhanglist = s1.collect(Collectors.toList());
zhanglist.add("阳光");
System.out.println(zhanglist);
//特别注意 注意 注意: 这里的流s1已经被终止了 只能再次创建流 才可以进行操作
//转换成 Set集合
Stream<String> s2 = list.stream().filter(s-> s.startsWith("张"));
Set<String> set = s2.collect(Collectors.toSet());
System.out.println(set);
//转换成数组 这里也需要再次创建流才可以继续操作
Stream<String> s3 = list.stream().skip(3);
Object[] array = s3.toArray();
System.out.println(Arrays.toString(array));
[张三, 张无忌, 张强, 张三丰, 张三丰, 阳光]
[张强, 张三, 张三丰, 张无忌]
[张无忌, 张强, 赵敏, 张三丰, 张三丰]