当前位置: 首页 > news >正文

探索 Java 8 中的 Stream 流:构建流的多种方式

在这里插入图片描述
人嘛,要懂得避嫌…

开篇引入

Java 8引入了Stream流作为一项新的特性,它是用来处理集合数据的一种函数式编程方式。Stream流提供了一种更简洁、高效和易于理解的方法来操作集合数据,同时也能够实现并行处理,以提高性能。

以下是Stream流的一些重要特征和用法:

  1. 流的创建:可以从集合、数组、I/O通道等多种数据源创建Stream流。例如,使用Collection.stream()方法可以将集合转换为流,使用Arrays.stream()可以将数组转换为流。

  2. 中间操作:Stream流支持各种中间操作,这些操作允许对流中的元素进行过滤、映射、排序等操作,而不会修改原始数据。一些常见的中间操作包括filter(过滤元素)、map(映射元素)、sorted(排序元素)等。

  3. 终端操作:终端操作是对流进行最终操作,它们触发实际的计算并生成结果。一些常见的终端操作包括forEach(遍历元素并执行操作)、collect(将流中的元素收集到一个集合中)、count(计算元素个数)等。

  4. 延迟执行:Stream操作是延迟执行的,这意味着中间操作可以在不实际计算的情况下链接在一起。只有在调用终端操作时,才会触发流的处理。

  5. 并行处理:Stream流支持并行处理,通过使用parallelStream()方法,可以轻松地将流的处理分布到多个处理器核心上,以提高性能。

  6. 函数式编程风格:Stream流鼓励使用函数式编程风格,其中操作是以lambda表达式的形式传递的,使代码更具表达力和简洁。

以下是一个示例,演示了如何使用Stream流来操作一个集合:

List<Integer> numbers = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10);int sum = numbers.stream().filter(n -> n % 2 == 0) // 过滤偶数.map(n -> n * 2) // 将偶数翻倍.reduce(0, Integer::sum); // 求和System.out.println("偶数的翻倍之和为: " + sum);

这只是Stream流的一个简单示例,它展示了Stream流的一些常见操作,如过滤、映射和汇总。通过Stream流,可以以更简洁和可读的方式处理集合数据,减少了样板代码,提高了代码质量和可维护性。下面我们将对构建流的多种方式多种方式展开做一个详细阐述。

1.从集合创建流

从集合创建Stream流非常简单,可以使用集合类的stream()方法来获取一个Stream对象。下面我将展示如何从集合创建Stream,并结合实际应用提供两个代码示例。

示例1:从List创建Stream

import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream;public class StreamCreationExample {public static void main(String[] args) {List<String> names = new ArrayList<>();names.add("Alice");names.add("Bob");names.add("Charlie");names.add("David");names.add("Eve");// 创建一个Stream流Stream<String> nameStream = names.stream();// 使用Stream流进行操作nameStream.filter(name -> name.startsWith("A")).forEach(System.out::println);}
}

这个示例中,我们首先创建了一个包含一些姓名的List集合,然后使用names.stream()方法创建了一个Stream流。接着,我们使用filter中间操作筛选出以"A"开头的姓名,并使用forEach终端操作打印输出结果。

示例2:从Map创建Stream

import java.util.HashMap;
import java.util.Map;
import java.util.stream.Stream;public class StreamCreationFromMapExample {public static void main(String[] args) {Map<Integer, String> studentMap = new HashMap<>();studentMap.put(1, "Alice");studentMap.put(2, "Bob");studentMap.put(3, "Charlie");studentMap.put(4, "David");studentMap.put(5, "Eve");// 从Map的键集合创建StreamStream<Integer> studentIdsStream = studentMap.keySet().stream();// 使用Stream流进行操作studentIdsStream.filter(id -> id % 2 == 0).forEach(id -> System.out.println(id + ": " + studentMap.get(id)));}
}

这个示例中,我们创建了一个包含学生ID和姓名的Map,然后使用studentMap.keySet().stream()方法从Map的键集合创建了一个Stream流。接着,我们使用filter中间操作筛选出偶数的学生ID,并使用forEach终端操作打印出相应的学生信息。

2.从数组创建流

从数组创建Stream流也非常简单,Java 8 提供了Arrays.stream() 方法,它允许将一个数组转换为一个Stream流。下面我将详细介绍如何从数组创建Stream,并提供两个代码示例。

示例1:从整数数组创建Stream

import java.util.Arrays;
import java.util.stream.IntStream;public class StreamCreationFromArrayExample {public static void main(String[] args) {int[] numbers = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};// 从整数数组创建IntStreamIntStream numberStream = Arrays.stream(numbers);// 使用Stream流进行操作int sum = numberStream.filter(n -> n % 2 == 0).map(n -> n * 2).sum();System.out.println("偶数的翻倍之和为: " + sum);}
}

在这个示例中,我们首先创建了一个整数数组 numbers,然后使用 Arrays.stream(numbers) 方法将它转换为一个 IntStream 流。接着,我们使用该流进行一系列操作,包括筛选出偶数并将其翻倍,最后计算它们的总和。

示例2:从字符串数组创建Stream

import java.util.Arrays;
import java.util.stream.Stream;public class StreamCreationFromArrayExample {public static void main(String[] args) {String[] words = {"apple", "banana", "cherry", "date", "elderberry"};// 从字符串数组创建StreamStream<String> wordStream = Arrays.stream(words);// 使用Stream流进行操作wordStream.filter(word -> word.startsWith("b")).map(String::toUpperCase).forEach(System.out::println);}
}

在这个示例中,我们创建了一个字符串数组 words,然后使用 Arrays.stream(words) 方法将它转换为一个 Stream 流。接着,我们使用流进行操作,包括筛选出以字母 “b” 开头的单词,并将它们转换为大写形式后打印输出。

3.静态工厂方法

Java 8也引入了一些静态工厂方法来创建Stream流,这些方法使得创建Stream流变得更加简便和灵活。下面我将详细介绍这些静态工厂方法,并提供两个代码示例。

静态工厂方法创建Stream

  1. Stream.of(T... values):通过将一个可变参数的元素列表传递给Stream.of方法来创建一个包含这些元素的Stream流。这对于创建具有少量元素的流非常方便。

  2. Stream.empty():使用Stream.empty()方法创建一个空的Stream流。

  3. Stream.generate(Supplier<T> s):通过提供一个Supplier函数来创建一个无限大小的Stream流,该函数会生成元素。通常,需要使用limit操作限制生成的元素数量。

  4. Stream.iterate(T seed, UnaryOperator<T> f):通过提供初始值(seed)和一个一元操作函数(UnaryOperator)来创建一个包含无限序列的Stream流。例如,可以使用Stream.iterate(0, n -> n + 1)来创建一个自然数序列的Stream流。

示例1:使用Stream.of创建Stream

import java.util.stream.Stream;public class StreamFactoryExample {public static void main(String[] args) {// 使用Stream.of创建Stream流Stream<String> stream = Stream.of("Apple", "Banana", "Cherry", "Date");// 打印Stream中的元素stream.forEach(System.out::println);}
}

这个示例使用Stream.of静态工厂方法创建了一个包含水果名称的Stream流,并使用forEach终端操作打印出每个水果的名称。

示例2:使用Stream.generate创建Stream

import java.util.Random;
import java.util.stream.Stream;public class StreamGenerateExample {public static void main(String[] args) {// 使用Stream.generate创建随机整数流Stream<Integer> randomIntStream = Stream.generate(() -> new Random().nextInt(100));// 限制流的元素数量,然后打印randomIntStream.limit(10).forEach(System.out::println);}
}

在这个示例中,我们使用Stream.generate静态工厂方法创建了一个包含随机整数的Stream流。然后,我们使用limit操作限制了流中元素的数量,最后打印出了生成的随机整数。

这些静态工厂方法为创建不同类型的Stream提供了便捷的途径,使流的创建更加灵活和便捷。

4.使用 Stream.Builder

Stream.Builder是Java 8引入的用于构建流的一种方式。它允许逐个添加元素到流中,并最终构建一个Stream对象。这对于在迭代或生成元素的过程中构建流非常有用。

下面是如何使用Stream.Builder创建流的详细介绍,并提供两个代码示例。

使用Stream.Builder创建流的步骤:

  1. 创建Stream.Builder对象:首先,需要创建一个Stream.Builder对象。

  2. 添加元素:然后,使用Stream.Builderadd方法逐个添加元素到流中。

  3. 构建流:一旦添加了所有元素,可以调用Stream.Builderbuild方法来构建Stream对象。

示例1:使用Stream.Builder创建流并过滤奇数

import java.util.stream.Stream;public class StreamBuilderExample {public static void main(String[] args) {Stream.Builder<Integer> builder = Stream.builder();// 添加元素到Streamfor (int i = 1; i <= 10; i++) {builder.accept(i);}// 构建StreamStream<Integer> numberStream = builder.build();// 使用Stream操作numberStream.filter(n -> n % 2 == 0) // 过滤偶数.forEach(System.out::println);}
}

在这个示例中,我们首先创建了一个Stream.Builder对象,然后使用accept方法逐个添加1到10的整数到流中,最后使用filter中间操作筛选出偶数并使用forEach终端操作打印出结果。

示例2:使用Stream.Builder生成斐波那契数列

import java.util.stream.Stream;public class FibonacciStreamExample {public static void main(String[] args) {Stream.Builder<Long> builder = Stream.builder();long a = 0, b = 1;int count = 10;for (int i = 0; i < count; i++) {builder.accept(a);long next = a + b;a = b;b = next;}Stream<Long> fibonacciStream = builder.build();fibonacciStream.forEach(System.out::println);}
}

在这个示例中,我们使用Stream.Builder生成斐波那契数列的前10个数字。我们首先创建一个Stream.Builder对象,然后使用循环逐个添加斐波那契数列的元素,最后使用forEach终端操作打印出结果。

Stream.Builder适用于需要逐个生成元素并构建流的情况,使代码更加清晰和灵活。

5. 从文件创建流

在Java中,可以从文件创建Stream流以便进行文件的读取和处理。通常,可以使用java.nio.file包中的类来实现这一目的。以下是如何从文件创建流的方法以及两个代码示例:

方法1:使用Files.lines方法创建文本文件的流

Files.lines方法允许创建一个包含文件内容的Stream<String>,适用于文本文件的逐行读取。该方法接受文件路径作为参数,并返回一个Stream对象。

下面是一个示例:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Paths;
import java.util.stream.Stream;public class FileToStreamExample {public static void main(String[] args) {String filePath = "sample.txt"; // 文件路径try (Stream<String> lines = Files.lines(Paths.get(filePath))) {lines.forEach(System.out::println); // 逐行打印文件内容} catch (IOException e) {e.printStackTrace();}}
}

在这个示例中,我们使用Files.lines方法打开名为"sample.txt"的文本文件,并将其内容逐行打印到控制台。

方法2:使用Files.newInputStream方法创建二进制文件的流

如果要处理二进制文件,例如图像或音频文件,可以使用Files.newInputStream方法创建一个InputStream,然后将其转换为Stream。下面是一个示例:

import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
import java.util.stream.Stream;public class BinaryFileToStreamExample {public static void main(String[] args) {String filePath = "image.jpg"; // 二进制文件路径try {Path path = Paths.get(filePath);Stream<Byte> byteStream = Files.newInputStream(path).map(b -> (byte) b);byteStream.forEach(System.out::println); // 逐字节打印二进制文件内容} catch (IOException e) {e.printStackTrace();}}
}

在这个示例中,我们使用Files.newInputStream方法创建一个输入流,然后将其映射为Stream<Byte>,并最终逐字节打印二进制文件的内容。

无论是文本文件还是二进制文件,从文件创建Stream流都是非常有用的,它使文件的读取和处理变得更加方便和灵活。在处理文件时,不要忘记适当地处理可能出现的IOException异常。

相关文章:

探索 Java 8 中的 Stream 流:构建流的多种方式

人嘛&#xff0c;要懂得避嫌… 开篇引入 Java 8引入了Stream流作为一项新的特性&#xff0c;它是用来处理集合数据的一种函数式编程方式。Stream流提供了一种更简洁、高效和易于理解的方法来操作集合数据&#xff0c;同时也能够实现并行处理&#xff0c;以提高性能。 以下是St…...

安卓Apk布局修改从入门到精通

安卓Apk布局修改从入门到精通 课程大纲 本次教程的目标是&#xff0c;学会将安卓apk反向工程后&#xff0c;如何找到需要修改的布局、对布局修改、对布局进行美化&#xff0c;如何隐藏布局&#xff08;按钮等&#xff09;&#xff0c;以及如何在界面上添加按钮并响应点击事件&…...

React Native 样式及其布局

React Native 样式及其布局 参考 https://reactnative.cn/docs/flexbox 一、样式 在 React Native 中&#xff0c;你并不需要学习什么特殊的语法来定义样式。我们仍然是使用 JavaScript 来写样式。所有的核心组件都接受名为style的属性。这些样式名基本上是遵循了 web 上的 …...

基于51单片机的智能指纹考勤系统设计

**单片机设计介绍&#xff0c;1661【毕设课设】基于51单片机的智能指纹考勤系统设计-原理图-PCB-程序-报告 文章目录 一 概要二、功能设计设计思路 三、 软件设计原理图 五、 程序六、 文章目录 一 概要 基于51单片机的智能指纹考勤系统是一种利用51单片机作为主控芯片&#x…...

I/O性能优化——这一篇就足够啦

背景 继上一篇CPU性能优化文章 &#xff0c;本次向大家分享关于I/O性能优化的分析套路以及常见措施。后续还有关于内存及网络优化的篇章。 基本概念 对于I/O我们先了解几个概念&#xff0c;文件系统&#xff0c;磁盘&#xff0c;文件。 磁盘 磁盘为系统提供了最基本的持久化存…...

【蓝桥杯选拔赛真题44】python小蓝晨跑 青少年组蓝桥杯python 选拔赛STEMA比赛真题解析

目录 python小蓝晨跑 一、题目要求 1、编程实现 2、输入输出 二、算法分析...

摩托车商家做展示预约小程序的作用

摩托车与电动车是人们短距离出行的主要工具&#xff0c;而其使用寿命一般是3年左右及以上、一家可能有多个&#xff0c;市场人群庞大且复购属性强&#xff0c;所以其经营商家也非常多。 如今互联网深入&#xff0c;在品牌宣传、客户获取、信息承载、营销等方面需要车辆经营商家…...

数据库实验:SQL的多表数据查询

目录 实验目的实验内容实验要求实验过程实验代码结果示意 书接上文&#xff0c;但是感觉之前的形式不太好用&#xff0c;至少不是很方便观看&#xff0c;所以这篇尝试改变一下写法&#xff0c;希望可以提升一些观感 实验目的 (1) 掌握RDBMS的数据多表查询功能 (2) 掌握SQL语言…...

【使用Python编写游戏辅助工具】第一篇:概述

引言 欢迎阅读本系列文章&#xff0c;本系列将带领读者朋友们使用Python来实现一个简单而有趣的游戏辅助工具。 写这个系列的缘由源自笔者玩了一款游戏。正巧&#xff0c;笔者对Python编程算是有一定的熟悉&#xff0c;且Python语言具备实现各种有趣功能的能力&#xff0c;因…...

Android与IOS渲染流程对比

目录 Android CPU计算图元信息 GPU干预 几何阶段等后处理 Android APP通过WindowManager统一提供所有Surface的缓冲区【不管是SurfaceView还是普通的布局流程都会将数据提交到Surface的BufferQuene中】 Java中的Surface是null&#xff0c;最终都是由Native层的Surface处理。…...

正则表达式以及 pattern 的撰写方式

正则表达式的撰写方法 在Python中,可以使用re模块来进行正则表达式的撰写和匹配。下面是一个基本的正则表达式撰写方法示例: 导入re模块: python import re定义正则表达式模式: python pattern = r正则表达式其中,r表示原始字符串,可以避免转义字符的问题。 使用re模…...

K8s Error: ImagePullBackOff 故障排除

Error: ImagePullBackOff 故障排除 1. 起因 起因是要在一组k8s环境下做个Prometheus的测试,当时虚拟机用完直接暂停了. 启动完master和node节点后重启了这些节点. 当检查dashboard时候发现Pod处于ImagePullBackOff状态,使用命令查看详细情况 kubectl describe pods -n kuber…...

爬虫之爬虫介绍、requests模块、携带请求参数、url 编码和解码、携带请求头

爬虫介绍 爬虫是什么&#xff1f; 网页蜘蛛&#xff0c;网络机器人&#xff0c;spider在互联网中 通过 程序 自动的抓取数据 的过程根上&#xff1a;使用程序 模拟发送http请求 ⇢ \dashrightarrow ⇢ 得到http响应 ⇢ \dashrightarrow ⇢ 把响应的数据解析出来 ⇢ \dashr…...

pytorch笔记:split

torch.split 是 PyTorch 中的一个函数&#xff0c;用于将张量按指定的大小或张量数量进行分割 1 基本使用方法 torch.split(tensor, split_size_or_sections, dim0)tensor要分割的输入张量split_size_or_sections以是整数或整数列表。 如果是整数&#xff0c;那么它表示每个分…...

K8S运维 解决openjdk:8-jdk-alpine镜像时区和字体问题

目录 一、问题 二、解决 三、完整代码 一、问题 由于项目的Dockerfile中使用openjdk:8-jdk-alpine作为基础镜像来部署服务&#xff0c;此镜像存在一定问题&#xff0c;例如时差8小时问题&#xff0c;或是由于字体问题导致导出excel文件&#xff0c;图片处理内容为空等。 二…...

Kubectl详解(陈述式、声明式)

目录 1、陈述式资源管理方法 1.1 基本信息查看 1.2 项目的生命周期&#xff1a;创建-->发布-->更新-->回滚-->删除 1.3 金丝雀发布&#xff08;Canary Release&#xff09; 2、声明式管理方法 1、陈述式资源管理方法 1.kubernetes 集群管理集群资源的唯一入口是…...

使用HttpClient库的爬虫程序

使用HttpClient库的爬虫程序&#xff0c;该爬虫使用C#来抓取内容。 using System; using System.Net.Http; using System.Threading.Tasks; ​ namespace CrawlerProgram {class Program{static void Main(string[] args){// 创建HttpClient对象using (HttpClient client new…...

VSIX:C#项目 重命名所有标识符(Visual Studio扩展开发)

出于某种目的&#xff08;合法的&#xff0c;真的合法的&#xff0c;合同上明确指出可以这样做&#xff09;&#xff0c;我准备了一个重命名所有标识符的VS扩展&#xff0c;用来把一个C#库改头换面&#xff0c;在简单的测试项目上工作很满意&#xff0c;所有标识符都被准确替换…...

【CSDN 每日一练 ★★☆】【动态规划】最小路径和

【CSDN 每日一练 ★★☆】【动态规划】最小路径和 动态规划 题目 给定一个包含非负整数的 m x n 网格 grid &#xff0c;请找出一条从左上角到右下角的路径&#xff0c;使得路径上的数字总和为最小。 说明&#xff1a;每次只能向下或者向右移动一步。 示例 示例 1&#x…...

前端学习之webpack的使用

概述 webpack是一个流行的前端项目构建工具&#xff08;打包工具&#xff09;&#xff0c;可以解决当前web开发中所面临的问题。 webpack提供了友好的模块化支持&#xff0c;以及代码压缩混淆、处理js兼容问题、性能优化等强大的功能&#xff0c;从而让程序员把工作重心放到具…...

谷歌浏览器插件

项目中有时候会用到插件 sync-cookie-extension1.0.0&#xff1a;开发环境同步测试 cookie 至 localhost&#xff0c;便于本地请求服务携带 cookie 参考地址&#xff1a;https://juejin.cn/post/7139354571712757767 里面有源码下载下来&#xff0c;加在到扩展即可使用FeHelp…...

(十)学生端搭建

本次旨在将之前的已完成的部分功能进行拼装到学生端&#xff0c;同时完善学生端的构建。本次工作主要包括&#xff1a; 1.学生端整体界面布局 2.模拟考场与部分个人画像流程的串联 3.整体学生端逻辑 一、学生端 在主界面可以选择自己的用户角色 选择学生则进入学生登录界面…...

css的定位(position)详解:相对定位 绝对定位 固定定位

在 CSS 中&#xff0c;元素的定位通过 position 属性控制&#xff0c;共有 5 种定位模式&#xff1a;static&#xff08;静态定位&#xff09;、relative&#xff08;相对定位&#xff09;、absolute&#xff08;绝对定位&#xff09;、fixed&#xff08;固定定位&#xff09;和…...

CMake 从 GitHub 下载第三方库并使用

有时我们希望直接使用 GitHub 上的开源库,而不想手动下载、编译和安装。 可以利用 CMake 提供的 FetchContent 模块来实现自动下载、构建和链接第三方库。 FetchContent 命令官方文档✅ 示例代码 我们将以 fmt 这个流行的格式化库为例,演示如何: 使用 FetchContent 从 GitH…...

python执行测试用例,allure报乱码且未成功生成报告

allure执行测试用例时显示乱码&#xff1a;‘allure’ &#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;ڲ&#xfffd;&#xfffd;&#xfffd;&#xfffd;ⲿ&#xfffd;&#xfffd;&#xfffd;Ҳ&#xfffd;&#xfffd;&#xfffd;ǿ&#xfffd;&am…...

sipsak:SIP瑞士军刀!全参数详细教程!Kali Linux教程!

简介 sipsak 是一个面向会话初始协议 (SIP) 应用程序开发人员和管理员的小型命令行工具。它可以用于对 SIP 应用程序和设备进行一些简单的测试。 sipsak 是一款 SIP 压力和诊断实用程序。它通过 sip-uri 向服务器发送 SIP 请求&#xff0c;并检查收到的响应。它以以下模式之一…...

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的“no matching...“系列算法协商失败问题

【SSH疑难排查】轻松解决新版OpenSSH连接旧服务器的"no matching..."系列算法协商失败问题 摘要&#xff1a; 近期&#xff0c;在使用较新版本的OpenSSH客户端连接老旧SSH服务器时&#xff0c;会遇到 "no matching key exchange method found"​, "n…...

es6+和css3新增的特性有哪些

一&#xff1a;ECMAScript 新特性&#xff08;ES6&#xff09; ES6 (2015) - 革命性更新 1&#xff0c;记住的方法&#xff0c;从一个方法里面用到了哪些技术 1&#xff0c;let /const块级作用域声明2&#xff0c;**默认参数**&#xff1a;函数参数可以设置默认值。3&#x…...

Neko虚拟浏览器远程协作方案:Docker+内网穿透技术部署实践

前言&#xff1a;本文将向开发者介绍一款创新性协作工具——Neko虚拟浏览器。在数字化协作场景中&#xff0c;跨地域的团队常需面对实时共享屏幕、协同编辑文档等需求。通过本指南&#xff0c;你将掌握在Ubuntu系统中使用容器化技术部署该工具的具体方案&#xff0c;并结合内网…...

WEB3全栈开发——面试专业技能点P7前端与链上集成

一、Next.js技术栈 ✅ 概念介绍 Next.js 是一个基于 React 的 服务端渲染&#xff08;SSR&#xff09;与静态网站生成&#xff08;SSG&#xff09; 框架&#xff0c;由 Vercel 开发。它简化了构建生产级 React 应用的过程&#xff0c;并内置了很多特性&#xff1a; ✅ 文件系…...