Java集合Stream流操作的基本使用教程分享
作者:码指星斗 发布时间:2023-09-01 01:05:03
标签:Java,Stream流,操作
Java 中可以使用 java.util.Stream
对一个集合(实现了java.util.Collection
接口的类)做各种操作,例如:求和、过滤、排序等等。
这些操作可能是中间操作——返回一个 Stream 流,或者是终端操作——返回一个结果。
流操作并不会影响原来的集合,可以简单认为,流操作是把集合中的一个元素逐个复制放到一个首尾相接的流动的水槽中。
Stream 流支持同步执行,也支持并发执行。如果我们直接获取 stream 流,得到的是同步执行的 stream 流;如果调用方法 parallelStream
,则得到一个可以并发执行的 Stream 流。
注意:Map
不支持 Stream 流,但是它的 Key
和 Value
支持,因为它们实现了 Set
接口。
事前准备
演示 Stream 流的提前准备,创建几个类以供测试
新建一个工具类,方便创建集合。
新建两个类,例如开发中常见的数据库实体类和 DTO 类。
public class MyUtil {
private static List<String> list = new ArrayList<>();
private static List<Student> students = new ArrayList<>();
static {
list.add("abc");
list.add("xyz");
list.add("fgh");
list.add("abc");
list.add("def");
list.add("xyz");
list.add("efg");
Student s1 = new Student();
s1.setAge("16");
s1.setId(UUID.randomUUID().toString());
s1.setName("张三");
s1.setMajor("计算机科学与技术");
Student s2 = new Student();
s2.setAge("18");
s2.setId(UUID.randomUUID().toString());
s2.setName("李四");
s2.setMajor("物联网工程");
Student s3 = new Student();
s3.setAge("20");
s3.setId(UUID.randomUUID().toString());
s3.setName("王五");
s3.setMajor("网络工程");
students.add(s1);
students.add(s2);
students.add(s3);
}
public static List<String> getList() {
return list;
}
public static List<Student> getStudents() {
return students;
}
}
public class Student {
private String id;
private String name;
private String age;
private String major;
}
public class StudentDTO {
private String name;
private String major;
}
Filter
filter 可以帮助我们过滤流中的某些元素,其方法签名如下
/*
过滤操作,
Predicate 相当于一个谓词,即断言流中的元素满足某个条件,返回一个 布尔值
*/
Stream<T> filter(Predicate<? super T> predicate);
具体使用方法如下:
public class Main {
public static void main(String[] args) {
List<String> list = MyUtil.getList();
System.out.println("过滤操作之前:");
System.out.println(list);
// 过滤不以 a 开头的字符串,collect() 将流中的元素放到一个新的集合中
List<String> newList = list.stream().filter(s -> !s.startsWith("a")).collect(Collectors.toList());
System.out.println("-------------------------");
System.out.println("过滤操作之后:");
System.out.println(newList);
}
}
======== 输出 =========
过滤操作之前:
[abc, xyz, fgh, abc, def, xyz, efg]
-------------------------
过滤操作之后:
[xyz, fgh, def, xyz, efg]
Sorted
sorted 可以帮助我们排序流中的元素,方法签名如下:
/*
中间操作,传入一个 Comparator,对流中的元素进行排序,如果不传入,则使用默认的 Comparable 排序
对原集合不影响
*/
Stream<T> sorted(Comparator<? super T> comparator);
具体使用方法如下:
public class Main {
public static void main(String[] args) {
List<String> list = MyUtil.getList();
System.out.println("排序操作之前:");
System.out.println(list);
List<String> newList = list.stream().sorted().collect(Collectors.toList());
System.out.println("-------------------------");
System.out.println("排序操作之后:");
System.out.println(newList);
System.out.println("自定义排序:");
// 倒序排序。 forEach 方法可以用传入的方法 逐个 处理流中的元素
list.stream().sorted((s1, s2)-> -s1.compareTo(s2)).forEach(System.out::println);
}
}
======== 输出 =========
排序操作之前:
[abc, xyz, fgh, abc, def, xyz, efg]
-------------------------
排序操作之后:
[abc, abc, def, efg, fgh, xyz, xyz]
自定义排序:
xyz
xyz
fgh
efg
def
abc
abc
Map
Map 操作可以帮助我们将流中的一类元素映射为另一类元素,最典型的应用就是可以用来将数据库实体类转换为供前端使用的 DTO 类。方法签名如下:
/*
中间操作,可以将一个对象转化为另一个对象
例如做 DTO 数据转换
*/
<R> Stream<R> map(Function<? super T, ? extends R> mapper);
具体使用方法如下:
public class Main {
public static void main(String[] args) {
List<Student> students = MyUtil.getStudents();
System.out.println("map 操作之前");
System.out.println(students);
// collect 方法可以将流中的元素收集到一个 Collection 中,如果有去除重复元素的需求,可以考虑收集到 Set 中
List<StudentDTO> dtos = students.stream().map(student -> {
StudentDTO dto = new StudentDTO();
dto.setName(student.getName());
dto.setMajor(student.getMajor());
return dto;
}).collect(Collectors.toList());
System.out.println("-------------------------");
System.out.println("map 操作之后");
System.out.println(dtos);
}
}
======== 输出 =========
map 操作之前
[Student{id='cb5726cd-e73a-443e-95e5-155aa6e876ae', name='张三', age='16', major='计算机科学与技术'}, Student{id='94478bae-b2ee-4c43-bac0-12f45f4099cd', name='李四', age='18', major='物联网工程'}, Student{id='5fdd9e19-f7cf-4c61-b506-0ef58a36dcbe', name='王五', age='20', major='网络工程'}]
-------------------------
map 操作之后
[StudentDTO{name='张三', major='计算机科学与技术'}, StudentDTO{name='李四', major='物联网工程'}, StudentDTO{name='王五', major='网络工程'}]
Match
/*
终端操作,可以用来匹配操作,返回一个 boolean 值
可以方便地匹配集合中是否存在某种元素
*/
// 只要集合中有一个匹配,就返回 true
boolean anyMatch(Predicate<? super T> predicate);
// 集合中所有元素都匹配,才返回 true
boolean allMatch(Predicate<? super T> predicate);
// 集合中所有元素都不匹配,返回 true
boolean noneMatch(Predicate<? super T> predicate);
具体使用方法如下:
public class Main {
public static void main(String[] args) {
List<String> list = MyUtil.getList();
System.out.println("集合中的所有元素是否都以 a 开头");
System.out.println(list.stream().allMatch(s -> s.startsWith("a")));
System.out.println("集合中是否存在元素以 a 开头");
System.out.println(list.stream().anyMatch(s -> s.startsWith("a")));
System.out.println("集合中的元素是否都不以 a 开头(相当于 allMatch 的取反):");
System.out.println(list.stream().noneMatch(s -> s.startsWith("a")));
}
}
======== 输出 =========
集合中的所有元素是否都以 a 开头
false
集合中是否存在元素以 a 开头
true
集合中的元素是否都不以 a 开头(相当于 allMatch 的取反):
false
Count
/*
终端操作,返回 stream 流中及集合中的元素个数,返回一个 long 类型
*/
long count();
具体使用方法如下:
public class Main {
public static void main(String[] args) {
List<String> list = MyUtil.getList();
System.out.println(list);
System.out.println("集合中的个数:" + list.size());
long count = list.stream().filter(s -> s.startsWith("a")).count();
System.out.println("集合中以 a 开头的元素个数:" + count);
}
}
======== 输出 =========
[abc, xyz, fgh, abc, def, xyz, efg]
集合中的个数:7
集合中以 a 开头的元素个数:2
Reduce
/*
终端操作,可以理解为减少集合的个数,对集合中的元素不断进行累加,最终只得到一个元素
Optional 包含一个对象,可以防止空指针异常
*/
Optional<T> reduce(BinaryOperator<T> accumulator);
具体使用方法如下:
public class Main {
public static void main(String[] args) {
List<String> list = MyUtil.getList();
// 可以理解为减少集合的个数,对集合中的元素不断进行累加,最终只得到一个元素
// 例如对数字集合进行累加进行求和
String s = list.stream().reduce((s1, s2) -> s1 + "###" + s2).get();
System.out.println(s);
}
}
======== 输出 =========
abc###xyz###fgh###abc###def###xyz###efg
来源:https://juejin.cn/post/7202153876438925372


猜你喜欢
- 序言:使用MyBatis3提供的注解可以逐步取代XML,例如使用@Select注解直接编写SQL完成数据查询,使用@SelectProvid
- 前言Spring内置的工具类里,最喜欢用的就是文件读写这一部分,虽然原生的写法也没几句,但是就是懒,不想循环、判断什么的,直接调用现成的静态
- 本文实例为大家分享了Unity shader实现高斯模糊效果的具体代码,供大家参考,具体内容如下正常图:高斯模糊效果图:shader代码:S
- Message的创建消息Message一般不支持大家直接通过new的方式进行创建的,因为Message作为Android系统中使用频率非常高
- 在我们开发过程中用 Mybatis 经常会用到下面的例子Mapper如下Map<String ,String > testArr
- 面试课题 Spring boot AOPSpring boot 中 AOP是其中 重要的特性,其实现的方式借助的 * + Proxy 动态
- 当你在使用Mybatis 时进行配置的时候有这样几个坑一定要注意下。mybatisplus中逻辑删除通俗说为了在数据库中保留数据,但是又不想
- JAVA中获取文件MD5值的四种方法其实都很类似,因为核心都是通过JAVA自带的MessageDigest类来实现。获取文件MD5值主要分为
- 由于 Spring 拥有对象的管理权,所以我们也需要拥有较为高效的对象存储和取出的手段,下面我们来分别总结一下:存对象配置文件在存储对象之前
- DSL的作用是解决领域专家与软件开发人员之间的沟通问题。听起来很唬人,其实不是什么高深的东西,我们可以使用Fluent API 创建自己的D
- 最近做了一个项目,其中有一个在线网页交流的需求,好久没写代码了,手都生疏了,于是先写demo练练手,分享到脚本之家平台,以此做个记录,方便自
- bufferedReader.readLine()读到最后发生阻塞最近在做一个imageserver,需求简化后就是使用socket响应HT
- 封装类用于阻止系统休眠的C#类。以下是代码注释的解释:DllImport("kernel32.dll"):定义了一个AP
- 安卓自定义分段式的进度条,供大家参考,具体内容如下前一段时间公司新项目接到一个新需求,其中界面需要用到一个分段式的进度条,找了半天没有发现类
- Fastjson是一个Java语言编写的高性能功能完善的JSON库。将解析json的性能提升到极致,是目前Java语言中最快的JSON库。F
- 先看下效果图:这个需要用到1个开源的 库,这个后面也会说下的。工程目录:1. MainActivity.javapublic class M
- 本文实例讲述了Android开发之imageView图片按比例缩放的实现方法。分享给大家供大家参考,具体如下:android:scaleTy
- 在java中,单例有很多种写法,面试时,手写代码环节,除了写算法题,有时候也会让手写单例模式,这里记录一下单例的几种写法和优缺点。1.初级写
- 本文实例讲解了通知Notification使用方法,此知识点就是用作通知的显示,包括振动、灯光、声音等效果,分享给大家供大家参考,具体内容如
- C#延时函数使用在线程中如果需要延时,尽量不要使用Sleep()函数,这样会导致时间片切到别的线程中。使用如下函数: