java Stream,让集合操作更丝滑

在jdk1.8之前,我们对于集合的处理都是比较麻烦的,比如:做一次过滤,就会在代码中使用for进行处理。jdk1.8后引入了Stream API来处理集合,使其变得简单。

1、Stream简介

Stream:流,可以对集合进行操作,比如:顾虑,合并等,是一种高效且易于使用处理数据的方法。
在Stream操作中分为三个步骤:

1、创建Stream流:比如:Stream.of()等
2、中间操作:即处理Stream流,比如:filter,map等
3、终止操作:即结束Stream流,返回操作结果,比如:collect(Collectors.toList())

在操作Stream时,Stream自己不会存储元素,不会改变原来对象,会延迟执行,只会在需要结果时才执行。

2、Stream常用方法

准备工作,创建一个专家实体,便于进行方法操作。

/**
* @author: jiangjs
* @description:
* @date: 2022/7/15 15:37
**/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Expert {

    private String name;
    private String gender;
    private Integer age;
}

创建一个集合:

List<Expert> experts = Arrays.asList(
                new Expert("jiashn","男",20),
                new Expert("张三-zhangsan","女",21),
                new Expert("王五-wangwu","女",26),
                new Expert("李四-lisi","男",24),
                new Expert("李四-lisi","男",24));

2.1 创建Stream

stream()或parallelStream():集合通过stream()可以创建顺序流,parallelStream()创建并行流。

experts.stream()

experts.parallelStream()

Stream.of():将数组转化成Stream流。

Stream<Expert> expertStream = Stream.of(new Expert("赵一-zhaoyi", "男", 20),
                new Expert("王定六-wangdingliu", "男", 21));

2.2 Stream中间操作

2.2.1 filter

filter(Predicate p):用于过滤满足条件的数据,例如:上述专家中查找年龄小于等于25岁的人员。
//过滤年龄小于等于25的人

List<Expert> filterExperts = experts.stream().filter(expert -> expert.getAge() <= 25).collect(Collectors.toList());
System.out.println("年龄小于等于25岁的人的信息:" + filterExperts);

输出:

年龄小于25岁的人的信息:[Expert(name=jiashn, gender=男, age=20),
Expert(name=张三-zhangsan, gender=女, age=21), Expert(name=李四-lisi,
gender=男, age=24)]

2.2.2 map和flatMap

map(Function f):将每个元素映射成新的元素,用于获取集合中某个元素的数据信息,例如:获取所有专家的名字。

//获取所以成员的名字信息
String names = experts.stream().map(Expert::getName).collect(Collectors.joining(","));
System.out.println("所有人员的名称:" + names);

输出:

所有人员的名称:jiashn,张三-zhangsan,王五-wangwu,李四-lisi

flatMap(Function<? super T, ? extends Stream<? extends R>> mapper):将流中每个值换成另一个流,并将所有流汇成一个流。例如:拆分名字,并获取名字信息。

 //拆分名字
List<String> splitName = experts.stream().flatMap(exp -> Stream.of(exp.getName().split("-")))
        .collect(Collectors.toList());
System.out.println("拆分名字结果:" + splitName);

输出:

拆分名字结果:[jiashn, 张三, zhangsan, 王五, wangwu, 李四, lisi]

2.2.3 sorted

sorted():排序,默认是升序排序,会产生一个新的流
sorted(Comparator<? super T> comparator):排序,按照比较器顺序排序,会产生一个新的流。例如:按照年龄进行排序

//年龄排序,正序或倒序
List<Expert> sortInfo = experts.stream().sorted(Comparator.comparing(Expert::getAge))
        .collect(Collectors.toList());
List<Expert> reversedInfo = experts.stream().sorted(Comparator.comparing(Expert::getAge).reversed())
        .collect(Collectors.toList());
System.out.println("人员年龄排序(升序):" + sortInfo+";人员年龄排序(降序):"+reversedInfo);

输出:

人员年龄排序(升序):[Expert(name=jiashn, gender=男, age=20), Expert(name=张三-zhangsan, gender=女, age=21), Expert(name=李四-lisi, gender=男, age=24), Expert(name=王五-wangwu, gender=女, age=26)];
人员年龄排序(降序):[Expert(name=王五-wangwu, gender=女, age=26), Expert(name=李四-lisi, gender=男, age=24), Expert(name=张三-zhangsan, gender=女, age=21), Expert(name=jiashn, gender=男, age=20)]

在比较器中使用.reversed()实现排序降序。

2.2.4 distinct()

distinct():去重,通过流所生成的hashCode()和equals()去除重复元素。例如:去重上面集合中的李四.

 //去重
List<Expert> disExperts = experts.stream().distinct()
        .collect(Collectors.toList());
System.out.println("去重:" + disExperts);

输出:

去重:[Expert(name=jiashn, gender=男, age=20), Expert(name=张三-zhangsan, gender=女, age=21), Expert(name=王五-wangwu, gender=女, age=26),Expert(name=李四-lisi, gender=男, age=24)]

2.2.5 limit、skip

limit(long maxSize):截断当前流,获取不超过给定数量的元素。
skip(long n):跳过元素,扔掉下标从0开始到n的元素的流,如果流中元素个数不超n个,则返回一个空流,与limit()互补。例如:获取下标从2开始的2个元素。

//截取记录信息
List<Expert> twoInfos = experts.stream().skip(2).limit(2).collect(Collectors.toList());
System.out.println("截取记录:"+twoInfos);

输出:

截取记录:[Expert(name=王五-wangwu, gender=女, age=26), Expert(name=李四-lisi,
gender=男, age=24)]

我们也可以使用skip、limit的组合来对返回回来的list数据进行分页操作。

2.3 Stream终止操作

终端操作从流的流水线生成结果。

2.3.1 allMatch、anyMatch、noneMatch

allMatch(Predicate p) :检查集合中所有元素是否与当前条件相匹配。例如:验证当前集合中元素性别是否都是男。
anyMatch(Predicate p) :检查当前集合中是否存在元素与当前条件相匹配。例如:验证当前集合中元素是否存在性别男。
noneMatch(Predicate p):检查当前集合元素是否所有元素与当前条件不匹配。例如:验证当前集合所有元素性别都不为男。

//allMatch
boolean allMatch = experts.stream().allMatch(expert -> Objects.equals(expert.getGender(), "男"));
System.out.println("是否性别都为男:"+allMatch);
//anyMatch
boolean ageMatch = experts.stream().anyMatch(expert -> Objects.equals(expert.getGender(), "男"));
System.out.println("是否存在性别为男:"+ageMatch);
//noneMatch
boolean noneMatch = experts.stream().noneMatch(expert -> Objects.equals(expert.getGender(), "男"));
System.out.println("所有元素性别不为男:"+noneMatch);

输出:

是否性别都为男:false
是否存在性别为男:true
所有元素性别不为男:false

2.3.2 findFirst、findAny()

findFirst():获取集合中的第一个元素信息,例如:获取集合第一个元素信息的姓名。
findAny():获取流中的任意元素,具有不确定性。

//findFirst
String name = experts.stream().findFirst().orElseGet(Expert::new).getName();
System.out.println("获取第一个元素的姓名:"+name);
//findAny
String anyName = experts.stream().findAny().orElseGet(Expert::new).getName();
System.out.println("获取符合条件任意元素的姓名:"+anyName);

输出:

获取第一个元素的姓名:jiashn
获取符合条件任意元素的姓名:jiashn

2.3.3 count

count():统计流中元素个数,可以与filter进行使用来统计符合条件的元素个数。例如:统计年龄大于23岁的人员个数

//count
long count = experts.stream().filter(expert -> expert.getAge() > 23).count();
System.out.println("年龄大于23岁的人员个数:"+count);

输出:

年龄大于23岁的人员个数:3

2.3.4 max、min

max(Comparator c) :返回流中符合条件的最大值。例如:获取集合年龄最大的元素信息。
min(Comparator c) :返回流中符合条件的最小值。例如:获取集合年龄最小的元素信息。

//max
Expert maxExpert = experts.stream().max(Comparator.comparing(Expert::getAge)).get();
System.out.println("年龄最大人员信息:"+maxExpert);
//min
Expert minExpert = experts.stream().min(Comparator.comparing(Expert::getAge)).get();
System.out.println("年龄最小人员信息:"+minExpert);

输出:

年龄最大人员信息:Expert(name=王五-wangwu, gender=女, age=26)
年龄最小人员信息:Expert(name=jiashn, gender=男, age=20)

2.3.5 forEach

forEach(Consumer c):内部循环,例如获取所有元素的姓名

//forEach
StringJoiner sj = new StringJoiner(",");
experts.forEach(expert -> sj.add(expert.getName()));
System.out.println("所有人员姓名:"+sj.toString());

输出:

所有人员姓名:jiashn,张三-zhangsan,王五-wangwu,李四-lisi,李四-lisi

当然也可以使用 map,Collectors.joining(“,”) 实现上述功能。参见map的使用。

2.3.6 reduce

reduce(T iden, BinaryOperator b):将流中元素反复结合起来,得到一个值,返回T
reduce(BinaryOperator b):将流中元素反复结合起来,得到一个值,返回Optional。例如:获取所有人员年龄的总和

//reduce
int totalAge = experts.stream().mapToInt(Expert::getAge).reduce(0, (total, age) -> {
    total += age;
    return total;
});
System.out.println("所有人员年龄总和:"+totalAge);

输出:

所有人员年龄总和:115

2.3.7 collect(Collector c)

collect(Collector c) :将流转换成其他形式。例如:list,set等。常用的方法:
toList:将流转换成list集合输出。上述例子中很多就用到
toSet:将流转换成set集合输出。例如:获取姓名
joining:连接流中每个元素,返回字符串,例如:运用map中的提到的获取所有用户姓名,使用","连接
groupingBy:分组,根据某些元素进行分组,例如:根据性别进行分组
partitioningBy:分区,根据true或false进行分区。例如:根据年龄大于23进行分区
summarizingDouble:汇总,统计元素的最大值,最小值等,例如:根据年龄进行汇总
当然stream还提供了其他的方法,如:counting,summingInt等。

//toSet
Set<String> nameSet = experts.stream().map(Expert::getName).collect(Collectors.toSet());
System.out.println("所有姓名:"+nameSet);

//groupingBy
Map<String, List<Expert>> genderMap = experts.stream().collect(Collectors.groupingBy(Expert::getGender));
System.out.println("性别分组信息:"+genderMap);

//summarizingDouble
DoubleSummaryStatistics statistics = experts.stream().collect(Collectors.summarizingDouble(Expert::getAge));
System.out.println("年龄最大值:"+statistics.getMax());
System.out.println("年龄最小值:"+statistics.getMin());
System.out.println("年龄平均值:"+statistics.getAverage());
System.out.println("年龄总和值:"+statistics.getSum());
System.out.println("总人数:"+statistics.getCount());

//partitioningBy
Map<Boolean, List<Expert>> collect = experts.stream().collect(Collectors.partitioningBy(jia -> jia.getAge() > 23));
List<Expert> gtExpert= collect.get(Boolean.TRUE);
List<Expert> ltExpert= collect.get(Boolean.FALSE);
System.out.println("年龄大于23岁的数据:"+gtExpert);
System.out.println("年龄小于等于23岁的数据:"+ltExpert);

输出:

所有姓名:[jiashn, 张三-zhangsan, 王五-wangwu, 李四-lisi]
性别分组信息:{女=[Expert(name=张三-zhangsan, gender=女, age=21), Expert(name=王五-wangwu, gender=女, age=26)], 男=[Expert(name=jiashn, gender=男, age=20), Expert(name=李四-lisi, gender=男, age=24), Expert(name=李四-lisi, gender=男, age=24)]}
年龄最大值:26.0
年龄最小值:20.0
年龄平均值:23.0
年龄总和值:115.0
总人数:5
年龄大于23岁的数据:[Expert(name=王五-wangwu, gender=女, age=26), Expert(name=李四-lisi, gender=男, age=24), Expert(name=李四-lisi, gender=男, age=24)]
年龄小于等于23岁的数据:[Expert(name=jiashn, gender=男, age=20),Expert(name=张三-zhangsan, gender=女, age=21)]

jdk1.8中的Stream的出现,让我们对集合的操作变得简单,业精于勤荒于嬉,我们多多使用,自然会对这些方法使用熟练掌握。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值