Java 8 Stream API可以怎么玩?

java8 Stream API java stream Java 8 java.util.stream Stream API的中间操作有filter、map、distinct、sorted、skip、limit、peek、mapToLong、mapToInt、mapToDouble、flatMap等 Stream API的终端操作有collect、max、min、count、allMatch、anyMatch、noneMatch、findFirst、findAny、forEach、toArray、reduce等。 阅读详情

Java 8新特性之一 Stream 的官方描述:

Classes in the new java.util.stream package provide a Stream API to support functional-style operations on streams of elements.

The Stream API is integrated into the Collections API, which enables bulk operations on collections, such as sequential or parallel map-reduce transformations.

Stream是一组用来处理数组、集合的API。

Java 8为什么引入函数式编程呢?简单说为了简洁,效率。

  • 函数式编程写出的代码简洁且意图明确,基本告别繁琐的for循环
  • 多核友好,函数式编程编写并行执行程序简单,调用一下parallel()方法就好

那么,使用Stream API怎么个简洁法呢?我们先来看一下Stream API给我们提供了哪些方法,然后实际操作一下,看看使用上有是不是真的很爽。

Stream API主要方法介绍

long count()

Returns the count of elements in this stream.

返回stream中的元素个数。

Stream distinct()

Returns a stream consisting of the distinct elements (according to Object.equals(Object)) of this stream.

返回由该流的不同元素(根据 Object.equals(Object) )组成的流。(也就是去重后组成的新的stream)

Stream filter(Predicate<? super T> predicate)

Returns a stream consisting of the elements of this stream that match the given predicate.

返回由与此给定谓词匹配的此流的元素组成的流。

Optional findAny()

Returns an Optional describing some element of the stream, or an empty Optional if the stream is empty.

返回描述流的一些元素的Optional如果流为空,则返回一个空的Optional 。

Optional findFirst()

Returns an Optional describing the first element of this stream, or an empty Optional if the stream is empty.

返回描述此流的第一个元素的可选项,如果流为空,则返回空的可选项。

void forEach(Consumer<? super T> action)

Performs an action for each element of this stream.

对该流的每个元素执行操作。

static Stream generate(Supplier s)

Returns an infinite sequential unordered stream where each element is generated by the provided Supplier.

返回无限顺序无序流,其中每个元素由参数Supplier生成 。

生成的是一个无限多元素的流,所以需要其他方法来限制一下。

static Stream iterate(T seed, UnaryOperator f)

Returns an infinite sequential ordered Stream produced by iterative application of a function f to an initial element seed, producing a Stream consisting of seed, f(seed), f(f(seed)), etc.

返回有序无限连续 Stream由函数的迭代应用产生 f至初始元素 seed ,产生 Stream包括 seed , f(seed) , f(f(seed)) ,等 。

Stream limit(long maxSize)

Returns a stream consisting of the elements of this stream, truncated to be no longer than maxSize in length.

返回由此流的元素组成的流,截短长度不能超过 maxSize 。

IntStream mapToInt(ToIntFunction<? super T> mapper)

Returns an IntStream consisting of the results of applying the given function to the elements of this stream.

返回一个 IntStream ,其中包含将给定函数应用于此流的元素的结果。

类似的还有 map() ,mapToDouble() ,mapToLong() 。

Optional max(Comparator<? super T> comparator)

Returns the maximum element of this stream according to the provided Comparator.

根据提供的 Comparator返回此流的最大元素。

类似的还有 min() 。

static Stream of(T t)

Returns a sequential Stream containing a single element.

返回包含单个元素的顺序 Stream 。

类似的还有 of(T... values) 。

Stream skip(long n)

Returns a stream consisting of the remaining elements of this stream after discarding the first n elements of the stream.

在丢弃流的第一个 n元素后,返回由该流的 n元素组成的流。

Stream peek(Consumer<? super T> action)

Returns a stream consisting of the elements of this stream, additionally performing the provided action on each element as elements are consumed from the resulting stream.

返回由该流的元素组成的流,另外在从生成的流中消耗元素时对每个元素执行提供的操作。

Stream sorted()

Returns a stream consisting of the elements of this stream, sorted according to natural order.

返回由此流的元素组成的流,根据自然顺序排序。

Stream sorted(Comparator<? super T> comparator)

Returns a stream consisting of the elements of this stream, sorted according to the provided Comparator.

返回由该流的元素组成的流,根据提供的 Comparator进行排序。

Object[] toArray()

Returns an array containing the elements of this stream.

返回一个包含此流的元素的数组。

玩一玩Stream API

关于Stream API,一般情况下是结合 Lambda表达式 来使用的。我们来看一下具体怎么操作。

Stream的创建

  1. 通过数组创建一个Stream

Arrays.stream(array)

/**
 * 通过数组创建Stream
 */
static void generateStreamByArray(){
    String[] str = {"行", "百", "里", "er"};
    Stream<String> arrStream = Arrays.stream(str);
    arrStream.forEach(System.out::print);
}

可以通过 stream.forEach(System.out::print) 这种 Lambda 表达式的方式打印 Stream 中的每个元素,运行结果:

行百里er
Process finished with exit code 0

  1. 通过集合创建一个Stream

list.stream()

static void generateStreamByList(){
    List<String> list = Arrays.asList("行", "百", "里", "er");
    list.stream().forEach(System.out::print);
    //list.forEach(System.out::print);
}

  1. 通过 generate 方法创建Stream

Stream.generate(Supplier s)

generate方法的参数是一个 Supplier 接口,这个接口的描述文档是:

说明 Supplier 是一个函数式接口,只有一个方法 get() ,因此我们可以用 Lambda 表达式来搞:

//Stream.generate
static void withGenerate() {
    Supplier<String> s = () -> "行百里er";
    //用limit方法限制生成的个数
    Stream.generate(s).limit(3).forEach(System.out::println);

    System.out.println("-----------------华丽的分割线-------------");

    Stream<String> stream = Stream.generate(() -> "行百里er");
    //用limit方法限制生成的个数
    stream.limit(3).forEach(System.out::println);
}

运行结果:

行百里er
行百里er
行百里er
-----------------华丽的分割线-------------
行百里er
行百里er
行百里er

Process finished with exit code 0

  1. 通过iterate方法创建Stream

Stream.iterate(seed, UnaryOperator)

通过调用 Stream 的 iterate 方法也能生成一个stream,该方法有2个参数,第一个参数是种子,专门为第二个参数 UnaryOperator 提供初始值,那么 UnaryOperator 又是个什么鬼呢?来看源码:

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}

说明 UnaryOperator 也是函数式的,表示对单个操作数执行的操作,该操作产生与其操作数类型相同的结果。

这是专门针对 操作数和对操作结果类型相同 这一类的。

比如我要产生一个stream,给定种子元素为2,产生3个元素,每个元素是是前一个元素的2倍,可以这样来:

//Stream.iterate(seed, UnaryOperator)
static void withIterate() {
    UnaryOperator<Integer> u = i -> i * 2;
    Stream.iterate(2, u).limit(3).forEach(System.out::println);

    System.out.println("---------华丽的分割线-----------");
    //等价于下面这种写法
    Stream.iterate(2, i -> i * 2).limit(3).forEach(System.out::println);
}

执行结果:

2
4
8
---------华丽的分割线-----------
2
4
8

Process finished with exit code 0

  1. 其他方式创建Stream

字符串的 chars() 方法也能生成stream,不过是 IntStream :

static void others() {
    IntStream chars = "行百里er".chars();
    //打印的是int类型
    chars.forEach(System.out::println);
}

运行结果:

34892
30334
37324
101
114

要想按照字符输出,做一下强制转换就行了:

static void others() {
    IntStream chars = "行百里er".chars();
    //打印的是int类型
    //chars.forEach(System.out::println);
    //可以将int转成char输出
    chars.forEach((c) -> System.out.print((char) c));
}

行百里er
Process finished with exit code 0

还有这种操作?

输出一个集合中所有的偶数

一句话搞定:

Arrays.asList(11, 2, 3, 4, 5, 19, 8, 18, 23).stream().filter((x) -> x % 2 == 0).forEach(System.out::println);

filter 方法的参数 Predicate<T> 也是函数式接口, 代表一个谓词(boolean-valued函数)的一个参数 。

计算一个集合中所有偶数的和

int sum = Arrays.asList(11, 2, 3, 4, 5, 19, 8, 18, 23).stream().filter((x) -> x % 2 == 0).mapToInt(x -> x).sum();

这里要注意的是,filter 出偶数之后要转成 IntStream ,才有 sum() 方法,用 mapToInt(ToIntFunction<? super T> mapper) 转即可。

参数ToIntFunction:表示产生值为int的结果的函数。这是专门为int- production转换提供的方法。

输出集合中的最大值、最小值

用 max() ,min() 方法:

List<Integer> intList = Arrays.asList(11, 2, 3, 4, 5, 6);
//输出最大值
Optional<Integer> maxOptional = intList.stream().max(Comparator.comparingInt(x -> x));
Integer max = maxOptional.get();
System.out.println("max:" + max);

//输出最小值
System.out.println(intList.stream().min(Comparator.comparingInt(x -> x)).get());

不用 max,min 也能实现,我们可以先排好序:

//输出最小值,先排好序,sorted不传参默认升序排序,找到第一个就是最小的了
System.out.println(intList.stream().sorted().findFirst().get());

//按照降序排序,再找第一个就是最大的了
System.out.println(intList.stream().sorted((x, y) -> y - x).findFirst().get());

集合去重

使用 distinct 方法或转成 Set :

//去重
Stream<Integer> distinctStream = Arrays.asList(1, 1, 2, 3, 5, 5, 3).stream().distinct();
distinctStream.forEach(System.out::println);
//去重方法二:转成Set
Set<Integer> collect = Arrays.asList(1, 1, 2, 3, 5, 5, 3).stream().collect(Collectors.toSet());
collect.forEach(System.out::println);

输出一个区域内的数字

比如,构造一个集合,里面存放1 ~ 50数字,要求输出21 ~ 30这10个数。

可以使用 iterate 方法构造stream,用 limit 限制为50个,然后调用 skip 方法跳过前20个,这时会返回一个从21 ~ 50的stream,我们只需在limit一下就可以满足只有20 ~ 30的stream了:

//输出21~30
Stream<Integer> stream = Stream.iterate(1, x -> x + 1).limit(50).skip(20).limit(10);
stream.forEach(System.out::println);

小结

  • Stream 不是集合元素,它不是数据结构并不保存数据,它是有关算法和计算的,它更像一个高级版本的 Iterator。

原始版本的 Iterator,只能显式地一个一个遍历元素并对其执行某些操作;

高级版本的 Stream,只要给出需要对其包含的元素执行什么操作,比如 “过滤掉长度大于 10 的字符串”、“获取每个字符串的首字母”等,Stream 会隐式地在内部进行遍历,做出相应的数据转换。

  • Stream不支持索引访问
  • Stream很容易生成数组或集合
  • Stream支持过滤,查找,转换,汇总,聚合等操作

 

详解Java8特性之Stream API 前言Java8中有两大最为重要的改变。第一个是Lambda表达式,还不了解的可以去这看看详解Java8特性之Lambda表达式另外一个则是Stream API,在java.util.stream下是什么Stream呢,很多地方说到它是处理集合的关键抽象概念,这样子说实在是太抽象了。这个Stream并不是我们以前认识的IO流,而是一个数据渠道,用于操作数据源(集合、数组等)所生成的元素序列。集合专注的 阅读详情

相关推荐

在Kotlin代码中要慎用Java 8 的 Stream API

因为会有性能损失。 测试代码: 1.Java 中直接使用 Java 8 的 Stream API: package i; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * @author: Jack * 2020-05-06 16:20 */ public class Str...

AI天才研究院 1万+

JDK8新特性总结

2019独角兽企业重金招聘Python工程师标准>>> ...

weixin_34056162的博客 251

Java 8 Stream API 基础教程

1995年4月1日,Java编程语言问世,被广泛应用于各个领域。Java平台提供了面向对象的编程能力、安全性、健壮性和可移植性。作为第一个支持动态类型和自动内存管理的多范型语言,Java在后续版本中不断增加新的功能特性,如Java SE 7、Java SE 8等。其中,Java 8也是一个值得关注的版本,因为它提供了一个全新的Stream API。Stream API是Java 8中新增的一个集合处理接口,其目的是对集合元素进行各种操作,如过滤、排序、映射、聚合等。

AI天才研究院 2143

Java8新特性Stream还有这种操作?

Java 8新特性之一Stream的官方描述: Classes in the new java.util.stream package provide a Stream API to support functional-style operations on streams of elements. The Stream API is integrated into the Collections API, which enables bulk operations on collections, su

hundred_li_journey的博客 859

告别迷茫!手把手教你用ArcGIS+GTB搞定生态源地MSPA分析(附避坑指南)

本文详细介绍了如何使用ArcGIS和GTB进行生态源地MSPA分析的全流程,包括软件安装、数据预处理、参数设置、结果可视化和常见问题排查。特别针对ArcGIS和GTB组合使用时的常见问题提供了避坑指南,帮助研究者高效完成生态规划任务。

weixin_30756499的博客 434

苹果开发者账号( Apple Developer)登录出现:你的 Apple ID 暂时不符合使用此应用程序的条件(您的apple账户不符合资格)

Apple开发对于新手来说确实可能会遇到各种问题,在遇到 Apple Developer 账号登录问题时,除了检查账号的安全性设置和协议确认外,还需要考虑账号的具体配置问题,比如主邮箱的设置。

Winter_Sun灬的博客 4134

Java8-9-Stream介绍与操作方式详解

转载:https://segmentfault.com/a/1190000012302965 Java8中的Stream与lambda表达式可以说是相伴相生的,通过Stream我们可以更好的更为流畅更为语义化的操作集合。Stream api都位于java.util.stream包中。其中就包含了最核心的Stream接口,一个Stream实例可以串行或者并行操作一组元素序列,官方文档中给出了一个示...

neymar_jr的博客 355

DBeaver连接ClickHouse保姆级教程:从安装到成功测试(附驱动下载问题解决)

本文提供了一份详细的DBeaver连接ClickHouse实战指南,重点解决了驱动下载失败等常见问题。文章从环境准备、DBeaver安装讲起,详细阐述了手动配置ClickHouse驱动的可靠方案,并逐步指导完成连接配置与测试,最后介绍了基础操作与查询优化技巧,旨在帮助用户高效完成连接并快速上手使用。

pink的博客 879

一起爪哇Java 8(三)——好用的Stream

Stream组成 在传统Java编程,或者说是类C语言编程中,我们如何操作一个数组数据呢?或者更泛化的讲,我们如何操作一个“集合”(Collection)数据呢?在Java中我们利用java.util包里的各种数据结构封装,来很好的表示了数组(Array)、集合(Set)、列表(List)和kv对象(Map)。但是抽象表示只是意味着存储和定义操作方法,具...

weixin_34107955的博客 358

【LTspice】002 第一个仿真电路

目录 1. 光偶元件的工作原理 2. 过零检测电路的工作原理 3. 以PC817光耦搭建一个过零检测电路 1. 光偶元件的工作原理 光耦合器(optical coupler,英文缩写为OC)亦称光电隔离器或光电耦合器,简称光耦。它是以光为媒介来传输电信号的器件。 PC817是一种把红外光发射器件和红外光接受器件以及信号处理电路等封装在同一管座内的器件。当输入电信号加到输入端发光器件LED上,LED发光,光接受器件接受光信号并转换成电信号,然后将电信号直接输出,或者将电信号放大处理成标准数字电平输

m0_59642765的博客 8023

Matlab 普通kriging(克里金)插值

Matlab 普通kriging(克里金)插值

dayuhaitang1的博客 4571

Java8 新特性 —— Stream API 详解

Stream作为Java 8的一大亮点,它专门针对集合的各种操作提供各种非常便利、简单、高效的API,Stream API主要是通过Lambda表达式完成,极大的提高了程序的效率和可读性,同时Stram API中自带的并行流使得并发处理集合的门槛再次降低,使用Stream API编程无需多写一行多线程的代码就可以非常方便的写出高性能的并发程序。使用Stream API能够使代码更加优雅。

知唔猪的博客 1933

Ceres&OpenCV 单目相机标定(论文复现)

Ceres&OpenCV 单目相机标定(论文复现)

dayuhaitang1的博客 370

Java 8 Stream流API解析

1. Stream流简介 Java 8 API添加了一个新的抽象称为流Stream,可以以一种声明的方式处理数据。 Stream流使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。 Stream流特点: 不是数据结构,不会保存数据,只是在原数据集上定义了一组操作 惰性求值,流在中间处理过程中,只是对操作进行了记录,并不会立即执行,需要等到执行终止操作的时候才会进行实际的计算 Stream不保存数据,它会将操作后的数据保存到另外一个对象中 一般使用步骤

xueguchen的博客 1万+

通过实例讲解瀑布模型

在电子商城开发中,瀑布模型如同 “工业时代的流水线”—— 能通过标准化流程交付高质量、高合规性的系统,但也可能因缺乏灵活性而错失市场机会。其优势与缺点本质上源于同一核心特征:严格的阶段性与文档驱动。决策建议若开发传统型、长周期、需求固定的电子商城(如企业内部采购平台),可优先选择瀑布模型,并通过 “需求预验证 + 模块化设计” 降低风险;若开发创新型、短周期、需快速迭代的电商平台(如社交电商、跨境电商),建议采用敏捷模型或混合模型(如瀑布 + Scrum),平衡规范性与响应速度。

跟佟格湾一起学习计算机知识吧~ 271

Altium Designer应用技巧1: 功能模块的复用方法

Altium Designer应用技巧1: 功能模块的复用方法      我们在使用Altium Designer进行电路图设计时,常会遇到功能模块的复用问题,例如我们经常需要将12V以DC-DC的方式转换成5V,这在很多线路板上都会应用到。现在我们普通的做法是,每个板子都重新绘制一遍,像这样DC-DC的电路,很浪费时间。那么如何采用提高工作效率呢?我们可以采取Altium Desi

snmplink的博客 1万+

Java8中的Stream API详解:Stream的背景及使用

摘要:      Stream是Java8的一大亮点,是对容器对象功能的增强,它专注于对容器对象进行各种非常便利、高效的 聚合操作(aggregate operation)或者大批量数据操作。Stream API借助于同样新出现的Lambda表达式,极大的提高编程效率和程序可读性。同时,它提供串行和并行两种模式进行汇聚操作,并发模式能够充分利用多核处理器的优势,使用fork/join并行方式来...

Rico's Blogs 8万+

温度PID控制PLC程序

温度PID稳定控制程序,适用于欧姆龙PLC,对其他PLC也具有很大参考价值

Java8 Stream API

所以JDK的做法是,把获取Stream的一部分方法封装到StreamSupport类,另一部分封装到Stream类,StreamSupport用来补足原先的集合体系,比如Collection,然后引入default方法包装一下,内部调用StreamSupport完成偷天换日。比如filter后面还可以跟map等操作,那么filter就是中间操作,而collect后返回的就是元素了,而不是流,无法继续使用。就好比一缕山泉,经过小草、小花、竹林,还是一缕水,但到了你的锅里煮成一碗粥,就没法继续使用了。

smart_an的专栏 2491

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

android 蓝牙通讯demo

android 下蓝牙通讯demo,实现了发现蓝牙,使能蓝牙,通过蓝牙发送消息。

Java8 Stream常用API整理

Java8中有两大最为重要的改变,第一个是Lambda表达式,另外一个则是Stream API。 流是Java8引入的全新概念,它用来处理集合中的数据。 众所周知,集合操作非常麻烦,若要对集合进行筛选、投影,需要写大量的代码,而流是以声明的形式操作集合,它就像SQL语句,我们只需告诉流需要对集合进行什么操作,它就会自动进行操作,并将执行结果交给你,无需我们自己手写代码。 在项目中使用Stre...

程铭程铭你快成名的博客 5812

java8 Stream API详解

文章目录一、Stream流概述二、创建Stream的方式相关API三、Stream的中间操作筛选与切片映射排序四、终止操作第一大类API(太过简单)第二大类AP归约收集 一、Stream流概述 1、java8中有两大最为重要的改变,第一就是Lambda表达式,另一个则是Stream API。 2、Stream API真正把函数式编程风格引入到Java中。这是目前为止,java类库中最好的补充,因为Stream API可以极大地提高java程序员的生产力,让程序员写出高效率、干净、简洁的代码。 3、Strea

qq_43842093的博客 1550

Java 8 Stream API 详解

Stream 是 Java 8 中处理集合数据的抽象工具。它并不是数据结构,而是一种对数据源(如集合、数组等)进行高效聚合操作的工具。声明式编程:通过链式调用方法描述数据处理逻辑。惰性求值:中间操作不会立即执行,只有在终端操作触发时才会执行。并行处理:可以轻松实现并行操作,充分利用多核 CPU。Stream API 是 Java 8 中非常强大的工具,它通过声明式的方式简化了集合数据的处理。通过掌握 Stream 的创建、中间操作和终端操作,你可以写出更简洁、高效的代码。Stream 的创建。

秃头之旅 1395

【Java】Java 8 Stream API

Stream 是对数据源(如集合、数组等)元素的序列化抽象,支持许多操作,如过滤、排序、映射等。sorted 方法对流中的元素进行自然排序,或者你可以传递一个自定义的比较器(Comparator)。(中间操作):一系列可以连接起来的操作,比如 filter、map、flatMap 等,这些操作不会执行任何处理,而是生成一个新的流。(终端操作):会触发之前所有的中间操作,并且产生结果,如 collect、forEach、reduce 等。(流):是一个来自某种数据源的元素队列,它支持连续的管道式操作。

鹏啊鹏 1155

Java 8 Stream API

中间操作是惰性操作(Lazy),它们不会立即执行,直到你触发一个终止操作时,才会开始执行整个流的计算。:用于将流中的元素通过函数转换成另一个类型的元素(通常是映射操作)。:将流中的每个元素映射成多个元素,然后再将所有这些元素合并成一个流。:将流中的元素收集到集合中,是最常用的终止操作。:检查流中的任何一个元素是否符合指定的条件。:用于过滤流中的元素,返回符合条件的元素。:对流中的每个元素进行操作,通常用于打印。:检查流中的所有元素是否符合指定的条件。:对流中的元素进行排序。:计算流中元素的数量。

缘友一世的博客 1406
上一篇: Maven 入门教程
下一篇: 使用无界队列的线程池会导致内存飙升吗?
Java技术那些事儿
博客等级 码龄5年 2306粉丝 2584原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值