Java8 Stream笔记

Java8学习笔记(四) —— Stream流式编程 Java8学习笔记系列: Java8学习笔记(一)—— 函数式编程的四个基本接口 Java8学习笔记(二)—— Lambda表达式 Java8学习笔记(三)—— Optional类的使用 Java8学习笔记(四) —— Stream流式编程 Java8学习笔记(五)—— 方法引用(::双冒号操作符) 一、什么是Stream? Stream API借助Lambda表达式... 阅读详情

什么是Stream?

Java 8 中的 Stream 是对数组和集合(Collection)对象功能的增强,
专注于对集合对象进行各种非常便利、高效的聚合操作,或者大批量数据操作。
 

Stream的特性?

➢ 不存储数据。Stream 是基于数据源的对象,它本身不存储数据元素,而是通过管道将数据源的元素传递给操作。

➢ 函数式编程。Stream 的操作不会修改数据源,例如filter不会将数据源中的数据删除。

➢ 延迟操作。Stream 的很多操作如filter,map等中间操作是延迟执行的,只有到终点操作才会将操作顺序执行。

➢ 可以解绑。对于无限数量的流,有些操作是可以在有限的时间完成的,比如limit(n) 或 findFirst(),
	这些操作可是实现”短路”(Short-circuiting),访问到有限的元素后就可以返回。

➢ 纯消费。Stream 的元素只能访问一次,类似Iterator,操作没有回头路,
	如果新访问流的元素,得重新生成一个新的流。

Stream的类型

➢ 串行流
	Collection.stream() 创建的串行流
	IntStream.range(int, int) 创建的串行流
	sequential() 方法可以将并行流转换成串行流。

➢ 并行流
	Collection.parallelStream() 为集合创建并行流
	parallel() 方法可以将串行流转换成并行流

Stream的操作类型

流的操作类型分为:中间操作、终止操作、短路操作

➢ 中间操作


一个流可以后面跟随零个或多个 中间(intermediate) 操作。
其目的主要是打开流,做出某种程度的数据映射/过滤,然后返回一个新的流,交给下一个操作使用。
这类操作都是惰性化的(lazy),就是说,仅仅调用到这类方法,并没有真正开始流的遍历。 

	○ map (mapToInt, flatMap 等) 映射,输入一个T类型的元素,返回一个R类型的元素;
		如果返回的类型是也是Stream类型,会直接把Stream放入原Stream中
	○ filter 筛选,匹配符合规则的元素
	○ distinct 筛选,通过hashcode 和 equals去除重复元素
	○ sorted 排序,按自然顺序排序,产生一个新流
	○ peek 用于查看每个元素,但不改变流的操作的方法。
		它接收一个Consumer类型的参数,该参数用于针对每个元素执行副作用操作。
		该方法返回一个与原始流相同的新流,因此可以进行链式操作。
	○ limit 筛选,取不超过给定数量的元素
	○ skip 筛选,跳过前n个元素,若流中元素不足n个则返回空流
	○ parallel 将串行流转换成并行流
	○ sequential 将并行流转换成串行流
	○ unordered 除去排序约束

➢ 终止操作

一个流只能有一个 终止(terminal) 操作,当这个操作执行后,流就被使用“光”了,无法再被操作。
所以这必定是流的最后一个操作。Terminal 操作的执行,才会真正开始流的遍历,
并且会生成一个结果,或者一个副作用(side effect)。

	○ forEach 遍历并逐个消费元素
	○ forEachOrdered 当多个线程并行处理时,按source原有的顺序输出
	○ toArray 把流转为数组
	○ reduce 规约,将流中元素按照指定规则合并成一个元素
	○ collect 收集,将流中元素收集到一个集合中
	○ min 返回流中最小的元素
	○ max 返回流中最大的元素
	○ count 统计流中元素个数
	○ anyMatch 流中元素是否有一个匹配规则p,有匹配返回true,无则false
	○ allMatch 流中元素是否全部匹配规则p,全部匹配返回true,否则false
	○ noneMatch 流中元素是否全部不匹配规则p
	○ findFirst 取流中第一个元素
	○ findAny 从流中任取一个元素
	○ iterator 将流转换为迭代器

➢ 短路操作

对于一个中间(intermediate) 操作,如果它接受的是一个无限流,它可以返回一个有限的新 Stream。
对于一个终止(terminal) 操作,如果它接受的是一个无限流,但能在有限的时间计算出结果。

如何创建Stream

Stream可以通过集合、数组或Stream自带的静态方法 of()、iterate()、generate() 来创建。

➢ 通过集合创建流


List<String> list = Arrays.asList("a", "b", "c");

// 创建顺序流
Stream<String> stream = list.stream();

// 创建并行流
Stream<String> parallelStream = list.parallelStream();

➢ 通过数组创建流

int[] array={1,3,5,6,8};

IntStream stream = Arrays.stream(array);

➢ 通过Stream自带的静态方法 of()、iterate()、generate() 创建流

// Stream.of 为给定元素创建顺序流
Stream<Integer> stream = Stream.of(1, 2, 3, 4, 5, 6);

// Stream.iterate 第一个参数是新流中的初始元素,
// 然后使用该数据做第二个参数也就是UnaryOperator函数的入参去计算第二元素,
// 然后把新计算得到的第二个元素作为入参继续计算第三个元素,以此循环可以制造无限个元素,
// 在实际使用中一般使用limit(n)方法去获取包含n个的流。
Stream<Integer> stream2 = Stream.iterate(0, (x) -> x + 3).limit(4);
stream2.forEach(System.out::println);

// Stream.generate 方法主要用于生成一个无限连续的无序流,流中的元素由用户定义的supplier函数生成。
Stream<Double> stream3 = Stream.generate(Math::random).limit(3);
stream3.forEach(System.out::println);

常用Api实例

➢ map

映射,输入一个T类型的元素,返回一个R类型的元素;

map(Function<? super T, ? extends R> mapper);

// 映射到其他对象
List<User> userList = list.stream().map(iteam -> {
            User user = new User();
            user.setSkuId(...)
            return user;
        }).collect(Collectors.toList());

// 取对象list中的一个属性为新的list
List<Integer> list2 = userList.stream()
                .map(User::getAge)
                .collect(Collectors.toList());

// 将字符串list中的字符串全大写
List<String> collect = strs.stream().map(String::toUpperCase).collect(Collectors.toList());

// 将字符串list中的字符长度
List<Integer> lengths = strs.stream().map(String::length).collect(Collectors.toList());


➢ reduce

归约是将集合中的所有元素经过指定运算,折叠成一个元素输出,
如:求最值、平均数等,这些操作都是将一个集合的元素折叠成一个元素输出。

reduce((T, T) -> T);
reduce(T, (T, T) -> T);

// 有初始值,计算年龄总和,两种写法都可:
int age = list.stream().reduce(0, (user1, user2) -> user1.getAge() + user2.getAge());
int sum = list.stream().map(User::getAge).reduce(0, (a, b) -> a + b);
int sum = list.stream().map(User::getAge).reduce(0, Integer::sum);

// 无初始值,此时返回的是Optional 类型
Optional sum = list.stream().map(User::getAge).reduce(Integer::sum);

➢ collect

收集Stream流到集合和指定集和中

//1.收集数据到list集合中
stream.collect(Collectors.toList())

//2.收集数据到set集合中
stream.collect(Collectors.toSet())

//3.收集数据到指定的集合中
stream.collect(Collectors.toCollection(HashSet::new))

数据聚合操作

//最大值
Collectors.maxBy();

//最小值
Collectors.minBy();

//总和
Collectors.summingInt();
Collectors.summingDouble();
Collectors.summingLong();

//平均值
Collectors.averagingInt();
Collectors.averagingDouble();
Collectors.averagingLong();

//总个数
Collectors.counting();


//或者使用lambda表达式取最大值
Optional<User> maxCollect2 = userList.stream().collect(Collectors.maxBy((s1, s2) -> s1.getJgid() - s2.getJgid()));

//或者使用lambda表达式取最小值
Optional<User> minCollect = userList.stream().collect(Collectors.minBy((s1, s2) -> s1.getJgid() - s2.getJgid()));

//或者使用lambda表达式取jgid总和
Integer sumCollect2 = userList.stream().collect(Collectors.summingInt(User::getJgid));

//或者使用lambda表达式取jgid平均值
Double avgScore2 = userList.stream().collect(Collectors.averagingInt(User::getJgid));

//(聚合)统计数量
Long count = userList.stream().collect(Collectors.counting());

分组操作

//接收一个 Function 参数
groupingBy(Function<? super T, ? extends K> classifier)

//或者使用lambda表达式
Map<Integer, List<User>> jgidMap2 = userList.stream().collect(Collectors.groupingBy(User::getJgid));

//jgid奇数一组偶数一组
Map<String, List<User>> jgidMap3 = userList.stream().collect(Collectors.groupingBy(s -> {
    if (s.getJgid() % 2 == 0) {
        return "jgid为偶数";
    } else {
        return "jgid为奇数";
    }
}));

//根据jgid分组,且规定为最大一组(规约:reducing)
Map<Integer, Optional<User>> jgidMap4 = 
		userList.stream().collect(Collectors.groupingBy(User::getJgid,
		       Collectors.reducing(BinaryOperator.maxBy(Comparator.comparing(User::getJgid)))
		));

多级分组操作

//接收两个参数: 1.Function 参数  2.Collector多级分组
groupingBy(Function<? super T, ? extends K> classifier,Collector<? super T, A, D> downstream) 

Map<Integer, Map<String, List<User>>> collect = 
				userList.stream().collect(Collectors.groupingBy(User::getJgid,
	                Collectors.groupingBy(user -> {
	                    if (user.getId() % 2 == 0) {
	                        return "id是偶数";
	                    } else {
	                        return "id是奇数";
	                    }
                })));

分区操作

根据返回值是否为 true,把集合分为两个列表,一个 true 列表,一个 false 列表。
和分组的区别在于分组可以有多个组,分区只会有两个区( true 和 false)

//1.一个参数
partitioningBy(Predicate<? super T> predicate)
 
//2.两个参数(多级分区)
partitioningBy(Predicate<? super T> predicate, Collector<? super T, A, D> downstream)

Map<Boolean, List<User>> collect = 
		userList.stream().collect(Collectors.partitioningBy(s -> {
            return s.getJgid() % 2 == 0;
        }));

stream.collect(Collectors.partitioningBy(s -> s % 2 == 0));

拼接操作

//无参数--等价于 joining("");
joining()

//一个参数,拼接符
joining(CharSequence delimiter)

//三个参数(拼接符+前缀+后缀)
joining(CharSequence delimiter, CharSequence prefix,CharSequence suffix)


String collect1 = userList.stream().map(User::getName).collect(Collectors.joining());
String collect2 = userList.stream().map(User::getName).collect(Collectors.joining(","));
String collect3 = userList.stream().map(User::getName).collect(Collectors.joining(",", "开始<", ">结束"));

toArray

toArray();
toArray(IntFunction<A[]> generator);


//1.使用无参,收集到数组,返回值为 Object[](Object类型将不好操作)
Object[] objects = userList.stream().toArray();

//2.使用有参,可以指定将数据收集到指定类型数组,方便后续对数组的操作
User[] user = userList.stream().toArray(User[]::new);


java8新特性——stream笔记 new Dish(“french fries”, true, 530, “鱼肉类”),new Dish(“chicken”, false, 400, “肉类”),new Dish(“prawns”, false, 300, “其他”),new Dish(“pizza”, true, 550, “鱼肉类”),new Dish(“pork”, false, 800, “肉类”),new Dish(“beef”, false, 700, “肉类”),list.stream() − 为集合创建串行流。 阅读详情

相关推荐

Java 8 Stream API 学习笔记

1970年代末,高级语言刚刚诞生时,计算机科学界还有着很长的一段时间没有可用的编程工具。像BASIC、COBOL、Fortran、Algol等等这些传统的语言,由于语法简单,并且支持变量、条件语句和循环结构,因此在当时的程序设计中起到了至关重要的作用。但随着编程技术的革新,面对越来越复杂的计算任务,这种语法上的限制也逐渐让开发者望而却步。在此背景下,程序员们开始寻找新的解决方案,希望能够编写出更加灵活、更加易读、更加高效的代码。

AI天才研究院 1370

Java8之Stream学习笔记

以下是一个包含多个Stream操作的示例程序,它涵盖了常用操作,主要针对List的操作,Lis中为对象。

weixin_42949219的博客 419

RTKLIB中RTK定位原理(一)

1 模型 1.1 非差观测值 非差观测值与RTKLIB中PPP定位原理——观测模型部分中一致。 1.2 单间单差观测值 若两个接收机距离较近,经过站间单差,电离层对流层延迟可消除,卫星s的钟差以及初始相位被消除,中依然包含接收机初始相位。 1.3 站间星间双差观测值 经过站间星间双差,接收机钟差及初始相位被消除。 2 EKF参数估计 2.1 EKF法则 EKF法则与RTKLIB中PPP定位原理——观测模型部分中一致。 2.2 状态变量与时间更新 (1)状态变量 在RTK...

papunzal的博客 3811

关于Java8中stream的笔记

简介 java8也出来好久了,接口默认方法,lambda表达式,函数式接口,Date API等特性还是有必要去了解一下。比如在项目中经常用到集合,遍历集合可以试下lambda表达式,经常还要对集合进行过滤和排序,Stream就派上用场了。用习惯了,不得不说真的很好用。 Stream作为java8的新特性,基于lambda表达式,是对集合对象功能的增强,它专注于对集合对象进行各种高效、便利的聚合操作...

代码搬运工的博客 196

Cadence学习之路:什么是PCB工艺的正片与负片

正片??负片??Flash焊盘的创建与使用

qq_46757048的博客 4245

java8学习笔记-Stream流Collector收集器

fun2为下游收集器,可以将列表转换成其他形式,例如toSet()、counting()、summingInt/Long/Double(fun)、maxBy(Comparator)、minBy(Comparator)、mapping(fun1, fun2)(fun1为转换函数,fun2为下游收集器)两个fun用来产生键和值,若值为元素本身,则fun2为Function.identity()fun是分类函数,生成Map,键是fun函数结果,值是具有相同fun函数结果元素的列表。

nimqbiyq的博客 947

电压电流双闭环PFC单相PWM整流

电压电流双闭环PFC单相整流。仿真及代码

xht2403267701的博客 6051

java8Stream笔记

转自:https://blog.youkuaiyun.com/mu_wind/article/details/109516995 先贴上几个案例,水平高超的同学可以挑战一下: 从员工集合中筛选出salary大于8000的员工,并放置到新的集合里。 统计员工的最高薪资、平均薪资、薪资之和。 将员工按薪资从高到低排序,同样薪资者年龄小者在前。 将员工按性别分类,将员工按性别和地区分类,将员工按薪资是否高于8000分为两部分。 用传统的迭代处理也不是很难,但代码就显得冗余了,跟Stream相比高下立判。 1 Strea

m0_46616045的博客 255

EPLAN二次开发入门:Visual Studio 2019环境配置与插件调试实战

本文详细介绍了EPLAN二次开发入门的关键步骤,重点讲解如何在Visual Studio 2019中配置开发环境并进行插件调试。通过创建符合命名规范的项目、引用核心API库、实现插件接口以及使用附加进程调试等实战技巧,帮助电气工程师快速掌握EPLAN插件开发,提升自动化设计效率。

h6i7j8的博客 763

Raspberry Pi Pico SDK开发-Timer-定时

RP2040 由 Raspberry Pi 设计,具有双核 Arm Cortex-M0+ 处理器和 264KB 内部 RAM,并支持高达 16MB 的片外闪存。 广泛的灵活 I/O 选项包括 I2C、SPI 和独特的可编程 I/O (PIO)。 本实例将演示如何使用Timer的定时功能。

视觉与物联智能 2040

java8学习笔记-Stream流

JDK1.8新增了Stream类,从而把函数式编程的风格引入到Java语言中,Stream类的API提供了强大的功能,使用Stream后,可以写出更加强大,更加简洁的代码关于应用在Stream流上的操作,可以分成两种:Intermediate(中间操作)和Terminal(终止操作)。中间操作的返回结果都是Stream,故可以多个中间操作叠加;终止操作用于返回我们最终需要的数据,只能有一个终止操作。至于哪些方法是中间操作,哪些方法是终止操作,我们一会儿再说。

nimqbiyq的博客 588

YOLOv11改进策略【卷积层】| TIP 2025 MFA 多阶段特征聚合 大核扩感受 + 多梯度融合,强效增强弱小目标特征

红外弱小目标尺寸极小、信噪比低,在特征传递中极易丢失信息;常规卷积感受野单一、梯度源不足,难以同时捕捉局部细节与全局上下文,导致小目标特征表达弱、检测漏检。因此提出多阶段特征聚合 MFA,用大核卷积+多分支+通道注意力强化小目标特征提取。

Limiiiing的博客 581

Java8 Stream学习笔记

在Java中,集合和数组是我们经常会用到的数据结构,需要经常对他们做增、删、改、查、聚合、统计、过滤等操作。相比之下,关系型数据库中也同样有这些操作,但是在Java 8之前,集合和数组的处理并不是很便捷。...

weixin_52894047的博客 3302

【车载以太网测试从入门到精通】系列文章目录汇总

物理层测试、数据链路层测试、以太网交换机测试、网络层测试、传输层测试、以太网TCP/IP协议自动化测试、以太网网络管理测试、以太网网络管理自动化测试、鲁棒性测试、SOME/IP测试、SOMEI/IP服务接口自动化测试、DoIP诊断测试、DoIP诊断自动化测试、DoIP BootLoader刷写、以太网网关路由测试、以太网网关路由自动化测试、AVB测试。

测试领域技术分享 3157

Data-Structures-and-Algorithm-Analysis-in-Java.pdf

作者: Weiss, Mark A. 出版社: Addison Wesley Data Structures and Algorithm Analysis in Java is an “advanced algorithms” book that fits between traditional CS2 and Algorithms Analysis courses. In the old ACM Curriculum Guidelines, this course was known as CS7. This text is for readers who want to learn good programming and algorithm analysis skills simultaneously so that they can develop such programs with the maximum amo...

Java8 stream 使用笔记

Java8 stream 使用笔记 1、分组 (1)分组查询 Map<String, List<InstallationPO>> collect = list.stream().collect(Collectors.groupingBy(InstallationPO::getpUser)); (2)分组统计 Map<String, Long> collect ...

Jason的博客 493

android 蓝牙通讯demo

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

Java8 Stream类学习笔记

今天看了一下午的Stream类,写点学习笔记,感觉还是理解不完全,应该还会有Stream类的后续笔记。 先贴一段采取Stream类实现的求一个String数组里所有质数的程序(请无视掉那个guava的com.google.common.collect.Lists的导入包): import java.util.List; import java.util.Arrays; import jav

wengeyiming的博客 508

RU DOS版、EFI版32bit/64bit BIOS常用工具

DOS版、EFI版的RU工具,可用来查看IO、MEM、PCI、SMBIOS等资源。亲测在EFI SHELL下可用。

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

【Java8】 Stream学习笔记

Java 8 是一个非常成功的版本,这个版本新增的Stream,配合同版本出现的 Lambda ,给我们操作集合(Collection)提供了极大的便利。那么什么是Stream?Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。Stream可以由数组或集合创建,对流的操作分为两种中间操作,每次返回一个新的流,可以有多个。终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。

qq_26127905的博客 1301

【java8 stream流 】 stream流 笔记

慢慢来也是诚意

汤圆的博客 228

Java8 Stream 分组求和使用笔记

Java8 Stream 分组求和使用笔记 话不多说,直接贴代码 public static void main(String[] args) { Foo foo1 = new Foo(1, 2); Foo foo2 = new Foo(2, 23); Foo foo3 = new Foo(2, 6); List&amp;amp;lt;Foo...

Kevan的博客 5万+

Java 8 Stream 学习笔记

先占个坑,过后来补充!

Beat_IT的博客 284

java8 stream的groupingBy笔记

1.业务需求 当时期望在通过groupingBy后,进行字段有序排列。但是一直未找到单使用groupingBy无法实现分组后对,分组的list进行内部直接排序的方。 通过groupingBy后转为LinkedHashMap已实现有序排列,通过遍历,对目标字段进行排序。实现要求的不同排序需求。 public static void main(String[] args) { List<PcSystem> arrayList = new A...

weixin_43213013的博客 427

java8特性 stream笔记(基础部分)

stream的简介 Java 8 API添加了一个新的抽象称为流Stream,Stream 使用一种类似用 SQL 语句从数据库查询数据的直观方式来提供一种对 Java 集合运算和表达的高阶抽象。这种风格将要处理的元素集合看作一种流, 流在管道中传输, 并且可以在管道的节点上进行处理, 比如筛选, 排序,聚合等。 Stream API可以极大提高Java程序员的生产力,让程序员写出高效率、干净、简洁的代码,其是以一种声明的方式处理数据。 /** * for循环写法与stream对比 */ class C

Ding_Creator的博客 234
上一篇: MySQL中NULL值与空值的坑
下一篇: Xsheel下sftp简单命令整理
star_falling
博客等级 码龄11年 287粉丝 21原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值