Java Stream函数式编程管道流结果处理

目录
  • 一、JavaStream管道数据处理操作
  • 二、ForEach和ForEachOrdered
  • 三、元素的收集collect
    • 3.1.收集为Set
    • 3.2.收集到List
    • 3.3.通用的收集方式
    • 3.4.收集到Array
    • 3.5.收集到Map
    • 3.6.分组收集groupingBy
  • 四、其他常用方法

一、Java Stream管道数据处理操作

在本号之前写过的文章中,曾经给大家介绍过 Java Stream管道流是用于简化集合类元素处理的java API。在使用的过程中分为三个阶段。在开始本文之前,我觉得仍然需要给一些新朋友介绍一下这三个阶段,如图:

  • 第一阶段(图中蓝色):将集合、数组、或行文本文件转换为java Stream管道流
  • 第二阶段(图中虚线部分):管道流式数据处理操作,处理管道中的每一个元素。上一个管道中的输出元素作为下一个管道的输入元素。
  • 第三阶段(图中绿色):管道流结果处理操作,也就是本文的将介绍的核心内容。

在开始学习之前,仍然有必要回顾一下我们之前给大家讲过的一个例子:

List<String> nameStrs = Arrays.asList("Monkey", "Lion", "Giraffe","Lemur");
List<String> list = nameStrs.stream()
        .filter(s -> s.startsWith("L"))
        .map(String::toUpperCase)
        .sorted()
        .collect(toList());
System.out.println(list);

首先使用stream()方法将字符串List转换为管道流Stream然后进行管道数据处理操作,先用fliter函数过滤所有大写L开头的字符串,然后将管道中的字符串转换为大写字母toUpperCase,然后调用sorted方法排序。这些API的用法在本号之前的文章有介绍过。其中还使用到了lambda表达式和函数引用。最后使用collect函数进行结果处理,将java Stream管道流转换为List。最终list的输出结果是:[LEMUR, LION]

如果你不使用java Stream管道流的话,想一想你需要多少行代码完成上面的功能呢?回到正题,这篇文章就是要给大家介绍第三阶段:对管道流处理结果都可以做哪些操作呢?下面开始吧!

二、ForEach和ForEachOrdered

如果我们只是希望将Stream管道流的处理结果打印出来,而不是进行类型转换,我们就可以使用forEach()方法或forEachOrdered()方法。

Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
        .parallel()
        .forEach(System.out::println);
Stream.of("Monkey", "Lion", "Giraffe", "Lemur", "Lion")
        .parallel()
        .forEachOrdered(System.out::println);

parallel()函数表示对管道中的元素进行并行处理,而不是串行处理,这样处理速度更快。但是这样就有可能导致管道流中后面的元素先处理,前面的元素后处理,也就是元素的顺序无法保证

forEachOrdered从名字上看就可以理解,虽然在数据处理顺序上可能无法保障,但是forEachOrdered方法可以在元素输出的顺序上保证与元素进入管道流的顺序一致。也就是下面的样子(forEach方法则无法保证这个顺序):

Monkey
Lion
Giraffe
Lemur
Lion

三、元素的收集collect

java Stream 最常见的用法就是:一将集合类转换成管道流,二对管道流数据处理,三将管道流处理结果在转换成集合类。那么collect()方法就为我们提供了这样的功能:将管道流处理结果在转换成集合类。

3.1.收集为Set

通过Collectors.toSet()方法收集Stream的处理结果,将所有元素收集到Set集合中。

Set<String> collectToSet = Stream.of(
   "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
)
.collect(Collectors.toSet());

//最终collectToSet 中的元素是:[Monkey, Lion, Giraffe, Lemur],注意Set会去重。

3.2.收集到List

同样,可以将元素收集到List使用toList()收集器中。

List<String> collectToList = Stream.of(
   "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
).collect(Collectors.toList());
// 最终collectToList中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]

3.3.通用的收集方式

上面为大家介绍的元素收集方式,都是专用的。比如使用Collectors.toSet()收集为Set类型集合;使用Collectors.toList()收集为List类型集合。那么,有没有一种比较通用的数据元素收集方式,将数据收集为任意的Collection接口子类型。
所以,这里就像大家介绍一种通用的元素收集方式,你可以将数据元素收集到任意的Collection类型:即向所需Collection类型提供构造函数的方式。

LinkedList<String> collectToCollection = Stream.of(
   "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
).collect(Collectors.toCollection(LinkedList::new));
//最终collectToCollection中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]

注意:代码中使用了LinkedList::new,实际是调用LinkedList的构造函数,将元素收集到Linked List。当然你还可以使用诸如LinkedHashSet::newPriorityQueue::new将数据元素收集为其他的集合类型,这样就比较通用了。

3.4.收集到Array

通过toArray(String[]::new)方法收集Stream的处理结果,将所有元素收集到字符串数组中。

String[] toArray = Stream.of(
   "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
) .toArray(String[]::new);
//最终toArray字符串数组中的元素是: [Monkey, Lion, Giraffe, Lemur, Lion]

3.5.收集到Map

使用Collectors.toMap()方法将数据元素收集到Map里面,但是出现一个问题:那就是管道中的元素是作为key,还是作为value。我们用到了一个Function.identity()方法,该方法很简单就是返回一个“ t -> t ”(输入就是输出的lambda表达式)。另外使用管道流处理函数distinct()来确保Map键值的唯一性。

Map<String, Integer> toMap = Stream.of(
    "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
)
.distinct()
.collect(Collectors.toMap(
       Function.identity(),   //元素输入就是输出,作为key
       s -> (int) s.chars().distinct().count()// 输入元素的不同的字母个数,作为value
));
// 最终toMap的结果是: {Monkey=6, Lion=4, Lemur=5, Giraffe=6}

3.6.分组收集groupingBy

Collectors.groupingBy用来实现元素的分组收集,下面的代码演示如何根据首字母将不同的数据元素收集到不同的List,并封装为Map。

Map<Character, List<String>> groupingByList =  Stream.of(
    "Monkey", "Lion", "Giraffe", "Lemur", "Lion"
)
.collect(Collectors.groupingBy(
       s -> s.charAt(0) ,  //根据元素首字母分组,相同的在一组
       // counting()        // 加上这一行代码可以实现分组统计
));
// 最终groupingByList内的元素: {G=[Giraffe], L=[Lion, Lemur, Lion], M=[Monkey]}
//如果加上counting() ,结果是:  {G=1, L=3, M=1}

四、其他常用方法

boolean containsTwo = IntStream.of(1, 2, 3).anyMatch(i -> i == 2);
// 判断管道中是否包含2,结果是: true
long nrOfAnimals = Stream.of(
    "Monkey", "Lion", "Giraffe", "Lemur"
).count();
// 管道中元素数据总计结果nrOfAnimals: 4
int sum = IntStream.of(1, 2, 3).sum();
// 管道中元素数据累加结果sum: 6
OptionalDouble average = IntStream.of(1, 2, 3).average();
//管道中元素数据平均值average: OptionalDouble[2.0]
int max = IntStream.of(1, 2, 3).max().orElse(0);
//管道中元素数据最大值max: 3
IntSummaryStatistics statistics = IntStream.of(1, 2, 3).summaryStatistics();
// 全面的统计结果statistics: IntSummaryStatistics{count=3, sum=6, min=1, average=2.000000, max=3}

以上就是Java Stream函数式编程管道流结果处理的详细内容,更多关于Stream管道流结果处理的资料请关注我们其它相关文章!

(0)

相关推荐

  • JAVA8 lambda表达式权威教程

    Java 8新特性----Stream流 jdk8是Java 语言开发的一个主要版本,它支持函数式编程,新的 JavaScript 引擎,新的日期 API,新的Stream API 等等.今天就重点介绍一个非常重要得特性之一 lambda表达式 一:什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 Java中的Stream并不会存储元素,而是按需计算. 数据源 流的来源. 可以是集合,数组,I/O channel, 产生器generator 等. 聚合操作 类似

  • Java输入输出流的使用详细介绍

    1.什么是IO Java中I/O操作主要是指使用Java进行输入,输出操作. Java所有的I/O机制都是基于数据流进行输入输出,这些数据流表示了字符或者字节数据的流动序列.Java的I/O流提供了读写数据的标准方法.任何Java中表示数据源的对象都会提供以数据流的方式读写它的数据的方法. Java.io是大多数面向数据流的输入/输出类的主要软件包.此外,Java也对块传输提供支持,在核心库 java.nio中采用的便是块IO. 流IO的好处是简单易用,缺点是效率较低.块IO效率很高,但编程比较

  • 解析Java8 Stream原理

    目录 一.前言 二.Stream流水线解决方案 2.1.操作如何记录 2.2.操作如何叠加 2.3.叠加之后的操作如何执行 一.前言 首先我们先看一个使用Stream API的示例,具体代码如下: 这是个很简单的一个Stream使用例子,我们过滤掉空字符串后,转成int类型并计算出最大值,这其中包括了三个操作:filter.mapToInt.sum.相信大多数人再刚使用Stream API的时候都会有个疑问,Stream是指怎么实现的,是每一次函数调用就执行一次迭代吗?答案肯定是否,因为如果真的

  • Java中stream处理中map与flatMap的比较和使用案例

    前言 使用Java8的新特性Stream流式处理,可以提高对于集合的一些操作效率,再配合lambda表达式,可以极致的简化代码,尤其还有并行流这个东东,可以去 了解一下,在一些场合还是可以提高效率的,而且编码起来也不费事. 并且流式处理的核心就是一个浅拷贝和引用管道,其内部实现了一个引用管道ReferencePipeline, 他把需要处理的数据的引用拷贝了一份,然后处理数据,最后收集结果也是将这些引用放到了另一个集合中. 今天要讲的就是stream处理中的map和flatMap这俩个的比较和使

  • Java Stream函数式编程管道流结果处理

    目录 一.JavaStream管道数据处理操作 二.ForEach和ForEachOrdered 三.元素的收集collect 3.1.收集为Set 3.2.收集到List 3.3.通用的收集方式 3.4.收集到Array 3.5.收集到Map 3.6.分组收集groupingBy 四.其他常用方法 一.Java Stream管道数据处理操作 在本号之前写过的文章中,曾经给大家介绍过 Java Stream管道流是用于简化集合类元素处理的java API.在使用的过程中分为三个阶段.在开始本文之

  • Java Stream函数式编程管道流结果处理

    目录 一.JavaStream管道数据处理操作 二.ForEach和ForEachOrdered 三.元素的收集collect 3.1.收集为Set 3.2.收集到List 一.Java Stream管道数据处理操作 在本号之前写过的文章中,曾经给大家介绍过 Java Stream管道流是用于简化集合类元素处理的java API.在使用的过程中分为三个阶段.在开始本文之前,我觉得仍然需要给一些新朋友介绍一下这三个阶段,如图: 第一阶段(图中蓝色):将集合.数组.或行文本文件转换为java Str

  • java中lambda(函数式编程)一行解决foreach循环问题

    java lambda(函数式编程)一行解决foreach循环 首先给大家推荐<精通lambda表达式:java多核编程> 这本书详细介绍了lambda表达式从入门到理解.应用 下面介绍用以前的循环方式进行对比,来更加清晰地java函数式编程中foreach的用法 一.以前我们使用的for循环 /** * for循环 */ @Test public void forTest() { // 实例化一个List List<Point> points = Arrays.asList(ne

  • Java8新特性:函数式编程

    首先需要清楚一个概念:函数式接口:它指的是有且只有一个未实现的方法的接口,一般通过FunctionalInterface这个注解来表明某个接口是一个函数式接口.函数式接口是Java支持函数式编程的基础. 1 Java8函数式编程语法入门 Java8中函数式编程语法能够精简代码. 使用Consumer作为示例,它是一个函数式接口,包含一个抽象方法accept,这个方法只有输入而无输出. 现在我们要定义一个Consumer对象,传统的方式是这样定义的: Consumer c = new Consum

  • java理论基础Stream管道流状态与并行操作

    一.回顾Stream管道流操作 通过前面章节的学习,我们应该明白了Stream管道流的基本操作.我们来回顾一下: 源操作:可以将数组.集合类.行文本文件转换成管道流Stream进行数据处理 中间操作:对Stream流中的数据进行处理,比如:过滤.数据转换等等 终端操作:作用就是将Stream管道流转换为其他的数据类型.这部分我们还没有讲,我们后面章节再介绍. 看下面的脑图,可以有更清晰的理解: 二.中间操作:有状态与无状态 其实在程序员编程中,经常会接触到“有状态”,“无状态”,绝大部分的人都比

  • java基础理论Stream管道流Map操作示例

    目录 一.回顾Stream管道流map的基础用法 二.处理非字符串类型集合元素 三.再复杂一点:处理对象数据格式转换 四.flatMap 一.回顾Stream管道流map的基础用法 最简单的需求:将集合中的每一个字符串,全部转换成大写! List<String> alpha = Arrays.asList("Monkey", "Lion", "Giraffe", "Lemur"); //不使用Stream管道流 L

  • Java函数式编程(七):MapReduce

    译注:map(映射)和reduce(归约,化简)是数学上两个很基础的概念,它们很早就出现在各类的函数编程语言里了,直到2003年Google将其发扬光大,运用到分布式系统中进行并行计算后,这个组合的名字才开始在计算机界大放异彩(那些函数式粉可能并不这么认为).本文我们会看到Java 8在摇身一变支持函数式编程后,map和reduce组合的首次亮相(这里只是初步介绍,后续还会有针对它们的专题). 对集合进行归约 现在为止我们已经介绍了几个操作集合的新技巧了:查找匹配元素,查找单个元素,集合转化.这

  • Java Stream流知识总结

    说明 在Java 8中,得益于Lambda所带来的函数式编程,引入了一个全新的Stream概念,用于解决已有集合类库既有的弊端 遍历 传统集合在于使用循环遍历 Java 8的Lambda让我们可以更加专注于做什么(What),而不是怎么做(How),这点此前已经结合内部类进行 了对比说明.现在,我们仔细体会一下上例代码,可以发现: for循环的语法就是"怎么做" for循环的循环体才是"做什么" 传统集合遍历 import java.util.ArrayList;

  • Java 函数式编程要点总结

    目录 一.函数式概念 二.函数与方法 三.JDK函数基础 1.Lambda表达式 2.函数式接口 四.Optional类 1.Null判断 2.Optional应用 五.Stream流 六.源代码地址 一.函数式概念 函数式编程是一种结构化编程的范式,主要思想是把运算过程尽量写成系列嵌套的函数调用.函数编程的概念表述带有很抽象的感觉,可以基于案例看: public class Function01 {     public static void main(String[] args) {   

  • 一篇文章带你了解Java Stream流

    目录 一.Stream流引入 现有一个需求: 1.用常规方法解决需求 2.用Stream流操作集合,获取流,过滤操作,打印输出 二.Stream流的格式 三.获取流 四.Stream流的常用方法 方法演示: 1.count方法: 2.filter方法: 3.forEach方法 4.limit方法 5.map方法 6.skip方法 7.concat方法 五.收集Stream流 总结 一.Stream流引入 Lambda表达式,基于Lambda所带来的函数式编程,又引入了一个全新的Stream概念,

随机推荐