用Java8 stream处理数据

目录
  • 1、stream处理数据介绍
  • 2、Stream起步
  • 3、Stream与Collection比较

1、stream处理数据介绍

  如果没有集合Collection你如何处理数据?几乎所有的Java应用程序都要使用Collection处理数据。他们是十分重要的编程工作:例如,您可能想要创建银行交易的集合Collection,这个集合代表客户的状态。然后,你可能要处理整个集合来找出的顾客花了多少钱。尽管集合如此重要,但是在Java中处理集合的技术还远远不够完善。

首先,对集合的典型处理模式是类似SQL操作,比如"finding"(例如,找到具有最高价的交易)或"grouping" (例如,将相关的杂物所有交易合并组) 。大多数数据库让您这样的声明方式指定的操作。例如,下面的SQL查询可以让您找到交易ID最高值: "SELECT id, MAX(value) from transactions" 。

正如你所看到的,我们并不需要实现如何具体计算最大值(例如,使用循环和一个变量来跟踪的最高值) 。我们只能表达我们所期望的要求(获得最大值)。只要我们显式发出这样的查询,数据库就会为我们去处理。可是为什么我们不能在集合Collection中实现类似的东西?多少次,你会发现自己使用循环一遍又一遍的反复遍历集合?(如:for Object o: myLists{ ..})

其次,如何才能有效地处理真正的大数据集合?在理想的情况下,你想利用多核架构加快处理,。然而,编写并行代码很难而且容易出错。

Java 8 API的设计者重新提出了一个新的抽象称为流Stream,可以让你以一种声明的方式处理数据。此外,数据流可以充分利用多核架构而无需编写多线程的一行代码。这听起来不错,不是吗?

首先,我们看看在Java 7中,如何发现typegrocery 的所有交易,然后返回以交易值降序排序好的交易ID集合?

List<Transaction> groceryTransactions = new Arraylist<>();

for(Transaction t: transactions){

  if(t.getType() == Transaction.GROCERY){

    groceryTransactions.add(t);

  }

}

Collections.sort(groceryTransactions, new Comparator(){

  public int compare(Transaction t1, Transaction t2){

    return t2.getValue().compareTo(t1.getValue());

  }

});

List<Integer> transactionIds = new ArrayList<>();

for(Transaction t: groceryTransactions){

  transactionsIds.add(t.getId());

}

而在Java 8使用Stream:

List<Integer> transactionsIds =

    transactions.stream()

                .filter(t -> t.getType() == Transaction.GROCERY)

                .sorted(comparing(Transaction::getValue).reversed())

                .map(Transaction::getId)

                .collect(toList());

我们首先从交易数据列表中获得一个stream对象,这是通过使用Liststream()方法实现的,下一步几个操作 (filter, sorted, map, collect)是以链式排列成一个管道,形成对数据的查询操作。

那么这段代码如何并行操作呢?那么只要更换transactions.stream()transaction.parallelStream()即可,请注意lambda表达式(t-> t.getCategory() == Transaction.GROCERY)和方法引用(Transaction::getId)将在下一章详细讲解。

2、Stream起步

首先,定义一下StreamStream是一个来自支持聚合操作源的元素的序列。

如下特点:

  1. 1. 所谓元素的序列,一个Stream向外提供了一个这样的接口:特定元素类型的值的序列,但是Stream并不实际持有也就是存储这些元素,它们是在有需求时才会被计算。
  2. 2. 源:以提供Stream进行计算消费的源,这些源有Collection集合 Array数组或I/O资源等。
  3. 3.聚合操作:Stream支持类似SQL操作和函数式编程的大部分操作,比如:filter, map, reduce, find, match, sorted。

此外,Stream操作不同于Collection操作有两个根本的地方:

  • 1.管道Pipelining: 许多流Stream操作返回流Stream自身,这就允许对其操作可以像链条一样排列,变成一个管道,这其中也会激活比如懒加载和short-circuiting操作。
  • 2.内部迭代:相比于集合Collection是显式迭代(需要我们编码完成迭代),Stream操作是在其内部完成迭代操作。

下面我们看看前面Stream代码的内部工作流程:

我们首先从交易transactions这个列表中获得Stream对象,数据源就是交易列表,其中提供了一系列元素集合,这些元素都是供Stream操作的,下一步,我们使用了一系列对这个Stream的聚合操作,包括过滤filter (用我们指定的谓词条件predicate过滤元素,也就是代码t -> t.getType() == Transaction.GROCERY), 排序(用指定的比较器comparator对元素进行排序), 以及 map (为了释放获取信息). 所有这些操作除了最后的collect操作,都是返回一个Stream对象,这样就能被前后链接在一起变成一个长的管道,可以看成是基于源数据集合的一个查询操作。如同SQL基于数据表的有条件查询语句一样。

最后到collect被调用操作, collect操作开始处理这个管道以返回一个结果,不再是一个结果流了,这里一个结果是List一个对象,我们看到collect接受一个recipe输入函数然后累计Stream中元素到一个汇总结果,这里输入函数是toList(),它是一个将将Stream转换为List对象。

3、Stream与Collection比较

StreamCollection集合有什么区别?Collection是关于静止的数据结构,而Stream是有关动词算法和计算的。前者是主要面向内存,存储在内存中,后者主要是面向CPU,通过CPU实现计算的。

举例将一个影片存储在DVD盘上,这是一个集合,因为它包含整个电影的字节数据结构,而这个影片被放在互联网上,我们通过视频软件去观看它时,它实际是被流化了,它变成了一个字节流,流是与时间有关的概念,而数据结构是与时间无关,不会随着时间变化变化,流正好相反,随着时间不断地动态变化,如同水流一样潺潺不断。

所以,集合与流的主要区别是是否需要被计算,集合是一个内存数据结构,集合中每个元素在加入到集合之前已经被计算了,相反,流是在即时要求即时计算。

使用集合需要开发者主动去遍历,使用一个遍历循环,这称为外部遍历。

而使用一个流库使用内部遍历,它自己为你遍历元素,然后将结果保存在某处,你只要提供一个函数,它就会用这个函数对元素处理完成。内外遍历的区别如下代码:

List<String> transactionIds = new ArrayList<>();

for(Transaction t: transactions){

    transactionIds.add(t.getId()); //外部遍历

}

List<Integer> transactionIds =

    transactions.stream()

                .map(Transaction::getId) //内部遍历

                .collect(toList());

到此这篇关于用Java8 stream处理数据的文章就介绍到这了,更多相关 stream处理数据内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java8 中的ParallelStream

    目录 1.Stream API 2.ParallelStreams执行原理 3.ParallelStreams注意事项 前言: 并行编程势不可挡,Java从1.7开始就提供了Fork/Join 支持并行处理.java1.8 进一步加强. 并行处理就是将任务拆分子任务,分发给多个处理器同时处理,之后合并. 1.Stream API Java 8 引入了许多特性,Stream API是其中重要的一部分.区别 InputStream OutputStream,Stream API 是处理对象流而不是字

  • Java BufferedOutputStream类的常用方法讲解

    目录 BufferedOutputStream类的常用方法 构造方式 常用方法 程序示例 BufferedOutputStream深入分析 代码准备 原因分析 手动刷盘 buffer源码分析 关于buf缓冲数据大小设置 BufferedOutputStream类的常用方法 BufferedOutputStream字节缓冲输出流 构造方式 第一种开发中 public BufferedOutputStream(OutputStream out) 采用的默认的缓冲区大小(足够大了) ,来构造一个字节缓

  • Java8特性之用Stream流代替For循环操作详解

    目录 准备一个实体类 准备一个List集合 传统的for循环 使用Stream流 先声明筛选条件,在遍历 Stream操作 嵌套循环(2层) 准备一个实体类 public class Student { private String name; private int age; public String getName() { return name; } public void setName(String name) { this.name = name; } public int get

  • 一文带你掌握Java8强大的StreamAPI

    目录 Stream 概述 Stream 实例化 1.方式一:通过集合 2.方式二:通过数组 3.方式三:通过Stream的of() 4.方式四:创建无限流 Stream 中间操作 1.筛选与切片 2.映射 3.排序 Stream 终止操作 1.匹配与查找 2.归约 3.收集 Stream 概述 Stream API ( java.util.stream) 把真正的函数式编程风格引入到Java中.这是目前为止对Java类库最好的补充,因为Stream API可以极大提供Java程序员的生产力,让程

  • Java8中Stream的一些神操作

    Java8对集合提供了一种流式计算的方式,这种风格将要处理的元素集合看 作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如 筛选, 排序,聚合等. Stream API 基本都是返回Stream本身,这样多个操作可以串联成一个管 道, 如同流式风格(fluent style). 这样做可以对操作进行优化, 比 如延迟执行(laziness)和短路( short-circuiting) stream() 为集合创建串行流 parallelStream() 为集合创建并行流 pri

  • Java实现InputStream的任意拷贝方式

    Java InputStream的任意拷贝 有时候,当我们需要多次使用到同一个InputStream的时候如何实现InputStream的拷贝使用 我们可以把InputStream首先转换成ByteArrayOutputStream.然后你就可以任意克隆你需要的InputStream了 代码如下: ByteArrayOutputStream baos = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int len; w

  • 用Java8 stream处理数据

    目录 1.stream处理数据介绍 2.Stream起步 3.Stream与Collection比较 1.stream处理数据介绍 如果没有集合Collection你如何处理数据?几乎所有的Java应用程序都要使用Collection处理数据.他们是十分重要的编程工作:例如,您可能想要创建银行交易的集合Collection,这个集合代表客户的状态.然后,你可能要处理整个集合来找出的顾客花了多少钱.尽管集合如此重要,但是在Java中处理集合的技术还远远不够完善. 首先,对集合的典型处理模式是类似S

  • 基于Java8 Stream API实现数据抽取收集

    目标&背景 我们以"处理订单数据"为例,假设我们的应用是一个分布式应用,有"订单应用","物流应用","商品应用"等都是独立的服务.本次我们的目的需要展示订单列表完整数据: 1.查询订单列表. 2.批量查询物流信息. 3.将物流信息填充到订单主信息中. 假设我们定义了一个订单类,具有几个关键的属性:订单号,状态,订单价,快递信息.如下所示: class Order{ String orderSeq; String st

  • Java8 Stream对两个 List 遍历匹配数据的优化处理操作

    使用场景,有两个List<Map<String,Object>>集合,第一个集合的所有元素都是需要保留的. 第一个集合的值为: {name=张三丰1, id=1} {name=张三丰2, id=2} {name=张三丰3, id=3} {name=张三丰4, id=4} {name=张三丰5, id=5} {name=张三丰6, id=6} {name=张三丰7, id=7} {name=张三丰8, id=8} 第二个集合的值为: {grade=61, id=1} {grade=6

  • Java8 Stream中间操作实例解析

    这篇文章主要介绍了Java8 Stream中间操作实例解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 介绍Stream Stream 使用一种类似用于SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象. Stream API可以极大提高Java程序员的生产力,让程序员写出高效率.干净.简洁的代码. 这种风格将要处理的元素集合看作一种流,流在管道中传输,并且可以在管道的节点上进行处理,比如筛选,排序,聚合等

  • Java8 Stream API 详细使用方法与操作技巧指南

    本文实例讲述了Java8 Stream API 详细使用方法与操作技巧.分享给大家供大家参考,具体如下: 1. 概述 Java 8 引入的一个重要的特性无疑是 Stream API.Stream 翻译过来是"流",突然想到的是大数据处理有个流式计算的概念,数据通过管道经过一个个处理器(Handler)进行筛选,聚合,而且流都具有向量性,强调的是对数据的计算处理,而集合强调的是数据集.Stream可以看做是一个可操作的数据集序列,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找.

  • 浅谈java8 stream flatMap流的扁平化操作

    概念: Steam 是Java8 提出的一个新概念,不是输入输出的 Stream 流,而是一种用函数式编程方式在集合类上进行复杂操作的工具.简而言之,是以内部迭代的方式处理集合数据的操作,内部迭代可以将更多的控制权交给集合类.Stream 和 Iterator 的功能类似,只是 Iterator 是以外部迭代的形式处理集合数据的操作. 在Java8以前,对集合的操作需要写出处理的过程,如在集合中筛选出满足条件的数据,需要一 一遍历集合中的每个元素,再把每个元素逐一判断是否满足条件,最后将满足条件

  • JAVA8 stream中三个参数的reduce方法对List进行分组统计操作

    背景 平时在编写前端代码时,习惯使用lodash来编写'野生'的JavaScript; lodash提供来一套完整的API对JS对象(Array,Object,Collection等)进行操作,这其中就包括_.groupBy 和 _.reduce,即分组和'聚合'(reduce不知道该怎么翻译合适). 使用这些'野生'的API能够极大的提高我本人编写JS代码的效率.而JAVA8开始支持stream和lambda表达式,这些和lodash的API有很多类似的功能.因此我在熟悉lodash的前提下尝

  • Java8 stream 中利用 groupingBy 进行多字段分组求和案例

    Java8的groupingBy实现集合的分组,类似Mysql的group by分组功能,注意得到的是一个map 对集合按照单个属性分组.分组计数.排序 List<String> items = Arrays.asList("apple", "apple", "banana", "apple", "orange", "banana", "papaya");

  • java8 stream sort自定义复杂排序案例

    java 8 自定义排序 需求 今天在项目中遇到个需求,按照对象中的三个属性进行排序. 具体要求: 前提:对象 Obj [a=a,b=b,c=c] 1. 优先级为a > b > c 2. a属性为中文,固定排序规则为:政府,合作,基金 - - 3. b的为BigDecimal类型,固定的排序规则为:降序排序 4. c为java.util.Date类型,规则为:降序排序 其实看这个需求,第3点和第4点不是什么问题,但是第1点,会考虑下怎么实现好. 直接上方案吧! 方案一 新建一张排序表,至少要有

  • 5分钟让你快速掌握java8 stream常用开发技巧

    前言 如果有些朋友以前没有使用过java8 stream这种链式编程方式做开发,想学习一下. 如果有些朋友只学习了一部分用法,想学习更多. 如果有些朋友想看看有没有好的示例适用于实际工作当中. 那么恭喜你,这篇文章非常适合你. 首先,我们一起看看stream的继承关系: Stream.IntStream.LongStream.DoubleStream的父接口都是BaseStream.BaseStream的四个子接口方法都差不多,只是IntStream.LongStream.DoubleStrea

随机推荐