Java SE8 流 最全总结

Java SE8 流

综述

如果我们要迭代的话,一般是进行这样的操作:

        ArrayList<Integer> contents = new ArrayList<Integer>(){
   {
   for(int i = 0; i < 100; i++){
    add(i * i);}}};
        //foreach迭代,进行计数操作
        int count = 0;
        for (int s : contents)
            if (s % 3 == 0)
                count++;
        System.out.println("能被3整除的数字有" + count + "个");

在java SE8之后,我们可以这样:

        ArrayList<Integer> contents = new ArrayList<Integer>(){
   {
   for(int i = 0; i < 100; i++){
    add(i * i);}}};
        //流操作
        int count = (int) contents.stream().parallel().mapToInt(s -> s).filter(s -> s % 3 == 0).count();
        System.out.println("能被3整除的数字有" + count + "个");

上面代码只是说明了流与for循环的不同,看起来似乎流的逼格更高,但流真正好处体现在哪里?


现在假设我们要设计一个学生管理系统,有一个需求:假设现在年纪里要评选奖学金,我们需要把全年级的学生根据综测排名,然后筛选出时长大于20的人,然后根据奖学金的数量选出人数,根据综测排名我们先分析一下步骤的实现:

  1. 输入所有学生信息
  2. 查重,将重复的学生信息删除
  3. 按绩点排序
  4. 选出前三个(假设奖学金只有三个)
  5. 按班分组
    可以想象用for循环来实现需要多少代码和逻辑,但是用流操作就很简单
    下面是代码实现:
        Map<Integer, List<Student>> map = students.stream()
                .parallel()
                .distinct()
                .sorted(Comparator.comparing(Student::getGPA).reversed())
                .filter((n) -> n.getVolunteerTime() > 20)
                .limit(3)
                .collect(Collectors.groupingBy(Student::getClassID));

ps:我们可以发现流的版本比循环的版本更简洁,可读性更高。因为我们不必扫描整个代码去查找过滤和计数操作。方法名就可以直接告诉我们其意欲何为。而且,循环需要非常详细的指定操作的顺序,而流就可以以其想要的任何代码来调度这些操作。

  • 流的操作不会修改其数据源,所有的操作都是生成一个新的流
  • 流的操作是尽可能的惰性执行,这意味着直至需要其结果时,操作才会执行。

总的来说,流的创建分为三步:

  1. 创建一个流:
        contents.stream()
  1. 将初始流转换为其他流的中间过程,可能包含很多步骤
  2. 终止操作。
//还有其他很多终止操作
        .count();

第一步 转换流的常用方法

  1. 将集合转化成流
    就像上面的代码,可以使用Connection接口的stream方法将任何集合转换成一个流
        ArrayList<Integer> contents =...;
        Stream<Integer> stream = contents.stream();
  1. 将数组转化成流
    使用静态的Stream.of()方法:这个方法接受一个数组,当然也支持可变参数,所以我们可以直接传值:
        Stream<Integer> stream = Stream.of(1,2,3,4,5,6);
  1. 创建一个空流
        Stream<Integer> stream = Stream.empty();
  1. 创建一个无限流
  • 使用静态方法generate(),下面是这个方法的定义
        public static<T> Stream<T> generate(Supplier<T> s)
  • 这个方法的参数是一个函数式接口,也就意味着我们可以用lambda表达式, 这段代码会生成一个无限流,流的内容全部都是1。
        Stream<Integer> stream = Stream.generate(() -> 1);
  • 或者下面这段代码,会生成一个无限随即数的流:
        Stream<Double> stream = Stream.generate(Math::random);
  • 生成自定义的无限流
    使用iterate()方法:
        public static<T> Stream<T> iterate(final T seed, final UnaryOperator<T> f)

第一个参数是种子,第二个参数的lambda表达式会对种子进行不断迭代:

        Stream
  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值