zoukankan      html  css  js  c++  java
  • Java-Stream流式计算

    什么是 Stream流式计算

    在 Java8 之前,如果我们想重新排序合并数据,一般是通过 for 循环或者 Iterator 迭代等方式进行操作。

    但是这两种方式通常在数据量比较大的情况下,效率比较低。

    在Java8中,添加了一个新的接口Stream,可以通过 Lambda 表达式对集合进行各种非常便利、高效的聚合操作(Aggregate Operation),或者大批量数据操作 (Bulk Data Operation)。

    Stream流式计算:将要处理的元素看做一种流,流在管道中传输,并且可以在管道的节点上处理,包括过滤筛选、去重、排序、聚合等,并把结果发送到下一计算节点。

    举例:对5个用户进行筛选

    • ID 必须是偶数
    • 年龄必须大于23岁
    • 用户名转为大写字母
    • 用户名字母倒着排序
    • 只输出一个用户!

    User类

    class User {
        int id, age;
        String name;
        public User() {}
        public User(int id, String name, int age) {
            this.id = id;
            this.name = name;
            this.age = age;
        }
        public int getId() {
            return id;
        }
        public int getAge() {
            return age;
        }
        public String getName() {
            return name;
        }
    }
    

    初始化的5个用户

    User u1 = new User(1,"a",21);
    User u2 = new User(2,"b",22);
    User u3 = new User(3,"c",23);
    User u4 = new User(4,"d",24);
    User u5 = new User(6,"e",25);
    

    使用传统的方式来实现

    List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
    List<String> nameList = new ArrayList<String>();
    for (User u : list) {
      if (u.getId() % 2 == 0)
        if (u.getAge() > 23)
          nameList.add(u.getName().toUpperCase());
    }
    nameList.sort(Comparator.reverseOrder());
    System.out.println(nameList.get(0));
    

    Stream进行实现

    List<User> list = Arrays.asList(u1, u2, u3, u4, u5);
    list.stream()
      .filter(u -> {
        return u.getId() % 2 == 0;
      })
      .filter(u -> {
        return u.getAge() > 23;
      })
      .map(u -> {
        return u.getName().toUpperCase();
      })
      .sorted((uu1, uu2) -> {
        return uu2.compareTo(uu1);
      })
      .limit(1)
      .forEach(System.out::println);
    

    Stream 操作分类

    Stream 的操作分为两大类:

    • 中间操作(Intermediate operations)

      • 只对操作进行了记录,即只会返回一个流,不会进行计算操作
      • 无状态(Stateless):元素的处理不受之前元素的影响
      • 有状态(Stateful):只有拿到所有元素之后才能继续下去
    • 终结操作(Terminal operations)

      • 终结操作是实现了计算操作
      • 短路(Short-circuiting):遇到某些符合条件的元素就可以得到最终结果
      • 非短路(Unshort-circuiting):必须处理完所有元素才能得到最终结果

    串行处理和并行处理

    • 串行处理操作

      • Stream 在执行每一步中间操作时,并不会做实际的数据操作处理,而是将这些中间操作串联起来,生成一个数据处理链表,通过 Spliterator 迭代器进行数据处理。
      • 每执行一次迭代,就对所有的无状态的中间操作进行数据处理,而对有状态的中间操作,就需要迭代处理完所有的数据,再进行处理操作
      • 最后进行终结操作的数据处理。
    • 并行处理操作(parallel()):

      • Stream 对中间操作基本跟串行处理方式是一样的
      • 终结操作中,Stream 将结合ForkJoin对集合进行切片处理,ForkJoin 框架将每个切片的处理结果 Join 合并起来

    建议

    在循环迭代次数较少的情况下,常规的迭代方式性能其实更好,尤其是服务器CPU只有单核

    服务器是多核 CPU 的情况下,Stream 的并行迭代优势明显。

    所以在平时处理大数据的集合时,应该尽量考虑将应用部署在多核 CPU 环境下,并且使用 Stream 的并行迭代方式进行处理

  • 相关阅读:
    jvm性能调优---jstat的用法
    flume-ng+Kafka+Storm+HDFS 实时系统搭建
    proxool
    Shell实现跳板机,为什么用跳板机
    JUC回顾之-ThreadPoolExecutor的原理和使用
    java集合之ArrayList的实现原理
    JMeter性能测试介绍学习一
    基础知识《十三》深入浅出Java回调机制
    怎样将myeclipse里默认编码设置成utf-8
    《转》怎样看待比自己强的人
  • 原文地址:https://www.cnblogs.com/aduner/p/14290373.html
Copyright © 2011-2022 走看看