Java 8新特性stream API用法总结

前言

  Stream 作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念。它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream。Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利、高效的聚合操作(aggregate operation),或者大批量数据操作 (bulk data operation)。Stream API 借助于同样新出现的 Lambda 表达式,极大的提高编程效率和程序可读性。同时它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用 fork/join 并行方式来拆分任务和加速处理过程。通常编写并行代码很难而且容易出错, 但使用 Stream API 无需编写一行多线程的代码,就可以很方便地写出高性能的并发程序。所以说,Java 8 中首次出现的 java.util.stream 是一个函数式语言+多核时代综合影响的产物。

怎么得到Stream

1、Stream接口的静态工厂方法

1、of方法:有两个重载方法,一个接受变长参数,一个接受单一值

Stream integerStream = Stream.of(1, 2, 3, 5);
Stream stringStream = Stream.of("taobao");

2、generator方法:生成一个无限长度的Stream,其元素的生成是通过给定的Supplier

Stream.generate(new Supplier() {
    @Override
    public Double get() {
        return Math.random();
    }
});
Stream.generate(() -> Math.random());
Stream.generate(Math::random);

上面三条语句的作用都是一样的,一般这种无限长度的Stream都会配合Stream的limit()方法来用。

3、iterate方法:也是生成无限长度的Stream,和generator不同的是,其元素的生成是重复对给定的种子值(seed)调用用户指定函数来生成的。其中包含的元素可以认为是:seed,f(seed),f(f(seed))无限循环

Stream.iterate(1, item -> item + 1).limit(10).forEach(System.out::println);

2、Collection接口的默认方法

Collection接口有一个stream方法,所以其所有子类都都可以获取对应的Stream对象。

1、调用Collection.stream()或者Collection.parallelStream()方法。

2、调用Arrays.stream(T[] array)方法

用法示例

1.forEach(): 对容器中的每个元素执行指定的动作,也就是对元素进行遍历。

Stream<String> stream = Stream.of("stream", "foreach", "method", "test");
stream.forEach(System.out::println);

2.filter(): 对某种条件进行过滤,然后返回一个新的stream

List<String> beginningWithNumbers
                = Stream.of("a", "1abc", "abc1")
                .filter(value -> isDigit(value.charAt(0)))
                .collect(toList());
assertEquals(Arrays.asList("1abc"), beginningWithNumbers);

3.map(): 对当前传入的流进行逻辑处理进行转换成另一个stream, 直观的说,就是对每个元素按照某种操作进行转换,转换前后Stream中元素的个数不会改变,但元素的类型取决于转换之后的类型。

List<String> collected = Stream.of("a", "b", "hello")
                .map(String::toUpperCase)
                .collect(toList());
assertEquals(Arrays.asList("A", "B", "HELLO"), collected);

4.flatMap(): 对每个元素执行mapper指定的操作,并用所有mapper返回的Stream中的元素组成一个新的Stream作为最终返回结果。说起来太拗口,通俗的讲flatMap()的作用就相当于把原stream中的所有元素都"摊平"之后组成的Stream,转换前后元素的个数和类型都可能会改变。

List<Integer> together = Stream.of(Arrays.asList(1, 2), Arrays.asList(3, 4))
                .flatMap(Collection::stream)
                .collect(toList());
assertEquals(Arrays.asList(1, 2, 3, 4), together);

5.reduce(): 规约操作(reduction operation)又被称作折叠操作(fold),是通过某个连接动作将所有元素汇总成一个汇总结果的过程。元素求和、求最大值或最小值、求出元素总个数、将所有元素转换成一个列表或集合,都属于规约操作。Stream类库有两个通用的规约操作reduce()collect(),也有一些为简化书写而设计的专用规约操作,比如sum()max()min()count()等。

  reduce操作可以实现从一组元素中生成一个值,sum()max()min()count()等都是reduce操作,将他们单独设为函数只是因为常用。reduce()的方法定义有三种重载形式:

Optional<T> reduce(BinaryOperator<T> accumulator)

T reduce(T identity, BinaryOperator<T> accumulator)

<U> U reduce(U identity, BiFunction<U,? super T,U> accumulator, BinaryOperator<U> combiner) 

  reduce()最常用的场景就是从一堆值中生成一个值.

// 找出最长的单词
Stream<String> stream = Stream.of("reduce", "optional", "test", "stream");
Optional<String> longest = stream.reduce((s1, s2) -> s1.length() >= s2.length() ? s1 : s2);
//Optional<String> longest = stream.max(Comparator.comparingInt(String::length));
assertEquals("optional", longest.get());
//数字求和int sum = Stream.of(1, 2, 3, 4)
                .reduce(0, (acc, element) -> acc + element);
assertEquals(10, sum);
// 求单词长度之和
Stream<String> stream = Stream.of("a", "bb", "ccc", "dddd");
int lengthSum = stream.reduce(0,            // 初始值 // (1)
    (sum, str) -> sum+str.length(),         // 累加器 // (2)
    (a, b) -> a+b);                         // 部分和拼接器,并行执行时才会用到 // (3)
// int lengthSum = stream.mapToInt(String::length).sum();
assertEquals(10, lengthSum);

6.collect(): 如果你发现某个功能在Stream接口中没找到,十有八九可以通过collect()方法实现。collect()Stream接口方法中最灵活的一个,学会它才算真正入门Java函数式编程

List<SaleOrderLineDO> newSaleOrderLines = saleOrderLines.stream()
            .map(oldSaleOrderLine -> {
                SaleOrderLineDO saleOrderLine = new SaleOrderLineDO();
                saleOrderLine.setId(oldSaleOrderLine.getId());
                saleOrderLine.setBuyerId(oldSaleOrderLine.getBuyerId());
                saleOrderLine.setReceiveQuantity(oldSaleOrderLine.getQuantity());
                saleOrderLine.setGmtModified(new Date());
                saleOrderLine.setModifier(modifier);
                return saleOrderLine;
            }).collect(Collectors.toList());

Map<Long, Integer> purchaseSendQuantityMap = realQuantities.stream()
            .collect(Collectors.toMap(RealQuantity::getSubLineId, RealQuantity::getSendQuantity));

7.Collectors

7.1.toList(): 将一个流转换成一个list集合返回

List<Integer> collect = listOne.stream().collect(Collectors.toList());

7.2.toMap(): 将一个流处理并返回一个hashMap对象

Map<String, Integer> collect = listOne.stream().collect(Collectors.toMap(k -> k.toString(), v -> v));

需要注意两点:
1.这里的入参都是stream流集合中的一个item,第一个返回值是hashMap的key,第二个返回值是hashMap的value.
2.如果hashMap的key有重复会throw duplicate

7.3.toSet(): 将一个流集合返回成一个set集合对象。可以用来去重。

Set<Integer> collect = listOne.stream().collect(Collectors.toSet());

7.4.groupingBy(): groupingBy默认模式是根据key来进行分组,并返回当前分组对象的map的list集合。

Map<Integer, List<Data>> collect2 = dataList.stream().collect(Collectors.groupingBy(Data::getCode));

当然你可以定制返回的分组对象集合:

Map<Integer, List<Integer>> collect3 = dataList.stream().collect(Collectors.groupingBy(Data::getCode, Collectors.mapping(x -> x.getCode(), Collectors.toList())));

可以通过mapping来对匹配到的list集合对象进行操作,可以返回自己期望的返回的对象。也可以用来进行排序:

TreeMap<Integer, List<Data>> collect2 = dataList.stream().collect(Collectors.groupingBy(Data::getCode, TreeMap::new, Collectors.toList()));

7.5.summarizing(): 将一个流集合转你成统计数据。包含了,平均值,总个数,最大值,最小值,总量。

IntSummaryStatistics collect = listOne.stream().collect(Collectors.summarizingInt(x -> x.intValue()));
        double average = collect.getAverage();
        long count = collect.getCount();
        int max = collect.getMax();
        int min = collect.getMin();
        long sum = collect.getSum();

参考文章:

https://www.ibm.com/developerworks/cn/java/j-lo-java8streamapi/

https://docs.oracle.com/javase/8/docs/api/java/util/stream/package-summary.html

原文地址:https://www.cnblogs.com/jeysin/p/10161819.html

时间: 2024-08-01 08:23:58

Java 8新特性stream API用法总结的相关文章

Java8新特性Stream API与Lambda表达式详解(1)

1 为什么需要Stream与Lambda表达式? 1.1  为什么需要Stream Stream作为 Java 8 的一大亮点,它与 java.io 包里的 InputStream 和 OutputStream 是完全不同的概念.它也不同于 StAX 对 XML 解析的 Stream,也不是 Amazon Kinesis 对大数据实时处理的 Stream.Java 8 中的 Stream 是对集合(Collection)对象功能的增强,它专注于对集合对象进行各种非常便利.高效的聚合操作(aggr

JAVA 8 新特性Stream初体验

什么是 Stream? Stream(流)是一个来自数据源的元素队列并支持聚合操作 <strong元素队列< strong="">元素是特定类型的对象,形成一个队列. Java中的Stream并不会存储元素,而是按需计算. 数据源 流的来源. 可以是集合,数组,I/O channel, 产生器generator 等. 聚合操作 类似SQL语句一样的操作, 比如filter, map, reduce, find, match, sorted等. 和以前的Collecti

Java 8新特性之旅:使用Stream API处理集合

在这篇“Java 8新特性教程”系列文章中,我们会深入解释,并通过代码来展示,如何通过流来遍历集合,如何从集合和数组来创建流,以及怎么聚合流的值. 在之前的文章“遍历.过滤.处理集合及使用Lambda表达式增强方法”中,我已经深入解释并演示了通过lambda表达式和方法引用来遍历集合,使用predicate接口来过滤集合,实现接口的默认方法,最后还演示了接口静态方法的实现. 源代码都在我的Github上:可以从 这里克隆. 内容列表 使用流来遍历集合. 从集合或数组创建流. 聚合流中的值. 1.

Java 8新特性之使用Stream API处理集合

1. 使用流来遍历集合 简介: Java的集合框架,如List和Map接口及Arraylist和HashMap类,让我们很容易地管理有序和无序集合.集合框架自引入的第一天起就在 持续的改进.在Java SE 8中,我们可以通过流的API来管理.遍历和聚合集合.一个基于流的集合与输入输出流是不同的. 如何工作? 它采用一种全新的方式,将数据作为一个整体,而不是单独的个体来处理.当你使用流时,你不需要关心循环或遍历的细节.你可以直接从一个集合创建一个流.然 后你就能用这个流来许多事件了,如遍历.过滤

Java SE 6 新特性: 编译器 API

新 API 功能简介 JDK 6 提供了在运行时调用编译器的 API,后面我们将假设把此 API 应用在 JSP 技术中.在传统的 JSP 技术中,服务器处理 JSP 通常需要进行下面 6 个步骤: 分析 JSP 代码: 生成 Java 代码: 将 Java 代码写入存储器: 启动另外一个进程并运行编译器编译 Java 代码: 将类文件写入存储器: 服务器读入类文件并运行: 但如果采用运行时编译,可以同时简化步骤 4 和 5,节约新进程的开销和写入存储器的输出开销,提高系统效率.实际上,在 JD

Java 8新特性

现在,是时候把所有Java8的重要特性收集整理成一篇单独的文章了,希望这篇文章能给你带来阅读上的乐趣.开始吧! 目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展注解的支持 Java编译器的新特性 3.1 参数名字 Java 类库的新特性 4.1 Optional 4.2 Streams 4.3 Date/Time API (JSR 310) 4.

Java 8新特性终极指南

目录结构 介绍 Java语言的新特性 2.1 Lambdas表达式与Functional接口 2.2 接口的默认与静态方法 2.3 方法引用 2.4 重复注解 2.5 更好的类型推测机制 2.6 扩展注解的支持 Java编译器的新特性 3.1 参数名字 Java 类库的新特性 4.1 Optional 4.2 Streams 4.3 Date/Time API (JSR 310) 4.4 JavaScript引擎Nashorn 4.5 Base64 4.6 并行(parallel)数组 4.7

Java 8 新特性 – 终极手册整理

1.简介 毫无疑问,Java 8是自Java  5(2004年)发布以来Java语言最大的一次版本升级,Java 8带来了很多的新特性,比如编译器.类库.开发工具和JVM(Java虚拟机).在这篇教程中我们将会学习这些新特性,并通过真实例子演示说明它们适用的场景. 本教程由下面几部分组成,它们分别涉及到Java平台某一特定方面的内容: 语言 编译器 类库 开发工具 运行时(Java虚拟机) 2.Java的新特性 总体来说,Java 8是一个大的版本升级.有人可能会说,Java 8的新特性非常令人

【整理】Java 8新特性总结

闲语: 相比于今年三月份才发布的Java 10 ,发布已久的Java 8 已经算是老版本了(传闻Java 11将于9月25日发布....).然而很多报道表明:Java 9 和JJava10不是 LTS 版本,和过去的 Java 大版本升级不同,它们只有半年左右的开发和维护期.而未来的 Java11,也就是 18.9 LTS,才是 Java 8 之后第一个 LTS 版本(得到 Oracle 等商业公司的长期支持服务).所以Java 8 就成了最新的一次LTS版本升级,这也是为什么Java开发者对J