Java中的Stream流

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));
[张三, 张无忌, 张强, 张三丰, 张三丰, 阳光]
[张强, 张三, 张三丰, 张无忌]
[张无忌, 张强, 赵敏, 张三丰, 张三丰]
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

RainbowCoder

你的鼓励将是我最大的动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值