收藏夹吃灰系列(十四):Java8 StreamAPI的详细用法 | 开箱即用,超级详细。
Posted bug菌√
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了收藏夹吃灰系列(十四):Java8 StreamAPI的详细用法 | 开箱即用,超级详细。相关的知识,希望对你有一定的参考价值。
目录:
Hi,我是bug菌,我又来啦。今日前来,不为别事,只想记录一篇自己对它的理解及使用,还请大家笑纳!途中如果有bug菌理解不对的地方,还请立即打断指正,以免误人,哈哈哈哈哈。
先请教大家一个问题,你们对java8 新特性熟悉吗?或者平时项目中,有那些新特性运用到了?可以评论区告诉bug菌,我会接下来的一段日子里根据大家的评论来恶补一些干货。比如:StreamAPI、Lambda 表达式、Date Time API等用法。
今天,我就要讲讲java8新特性之Stream API,尽量做到句句是重点。
一、概述
Stream 是 Java8 中处理集合的关键抽象概念,它可以指定你希望对集合进行的操作,可以执行非常复杂的查找、过滤和映射数据等操作。
使用Stream API 对集合数据进行操作,就类似于使用 SQL 执行的数据库查询。也可以使用 Stream API 来并行执行操作。
简而言之,Stream API 提供了一种高效且易于使用的处理数据的方式。
二、概念
1、Stream是什么
Stream其实是一个集合元素的函数模型,它并不是集合,也不是数据结构,其本身并不存储任何元素(或其地址值)。
Stream将要处理的元素集合看作一种流,在流的过程中,借助Stream API对流中的元素进行操作,比如:筛选、排序、聚合等。
2、Stream特性
- stream不存储数据,而是按照特定的规则对数据进行计算,一般会输出结果。
- stream不会改变数据源,通常情况下会产生一个新的集合或一个值。
- stream具有延迟执行特性,只有调用终端操作时,中间操作才会执行。
3、Stream创建方式
Stream可以由数组或集合创建。如下所示:
i、方式一:
通过 java.util.Collection.stream() 方法用集合创建流
List<String> strs = Arrays.asList("a", "b", "c");
// 创建一个顺序流
Stream<String> stream = strs.stream();
// 创建一个并行流
Stream<String> parallelStream = strs.parallelStream();
ii、方式二:
通过java.util.Arrays.stream(T[] array)方法用数组创建流
String[] strs = new String[8];
Stream<String> stream = Arrays.stream(strs );
4、流操作分类
对流的操作可分为两种:
- 中间操作,每次返回一个新的流,可以有多个。
- 终端操作,每个流只能进行一次终端操作,终端操作结束后流无法再次使用。终端操作会产生一个新的集合或值。
5、使用流程
当使用一个流的时候,通常包括三个基本步骤:获取一个数据源(source) → 数据转换→执行操作获取想要的结果,每次转换原有 Stream 对象不改变, 返回一个新的 Stream 对象(可以有多次转换),这就允许对其操作可以像链条一样排列,变成一个管道。
6、stream 区分 parallelStream
stream是顺序流,由主线程按顺序对流执行操作。
parallelStream是并行流,内部以多线程并行执行的方式对流进行操作,但前提是流中的数据处理没有顺序要求。
7、Stream 中的静态方法
如下我将一一列举及解释其用法,尽可能做到句句是重点。
a、of()
用于为给定元素创建一个顺序流。如下代码示例:
//用于为给定元素创建顺序流
Stream<Integer> stream1 = Stream.of(1, 2, 3, 4, 5);
stream1.forEach(System.out::print);//1 2 3 4 5
b、iterate()
指定一个常量seed,生成从seed到常量f(由UnaryOperator返回的值得到)的流。如下代码示例:
//根据起始值seed(0),每次生成一个指定递增值(n+1)的数,limit(5)用于截断流的长度,即只获取前5个元素。
Stream.iterate(10, x -> x + 10).limit(5).forEach(System.out::print);//10 20 30 40 50
c、concat()
合并两个流。如下代码示例:
String[] strs = "a","b","c";
Integer[] ints = 1,2,3;
Stream concat = Stream.concat(Arrays.stream(strs), Arrays.stream(ints));
concat.forEach(System.out::print);//abc123
d、generate()
流generate(Supplier s) 返回无限顺序无序流,其中每个元素由提供的供应商生成。
// 这适用于生成恒定流,随机元素流等。
Stream.generate(new Random()::nextInt).limit(5).forEach(System.out::println);//1149006011 -703426624 774541719 942720678 1437848577
e、empty()
创建一个空顺序流。如下代码示例:
Stream<String> empty = Stream.empty();
empty.forEach(System.out::println);//无输出
f、builder()
构建流。如下代码示例:
Stream.Builder<String> builder = Stream.builder();
builder.add("a");
builder.add("b");
builder.add("c");
builder.add("d");
builder.add("e");
builder.build().forEach(System.out::print); //abcde
三、实战演练
接下来,大批代码向你袭来!我将用几个真实案例将Stream使得明明白白,你只需要跟着敲一遍,你就能学会。
案例使用的实体类。如下:
/**
* 用户基本信息实体
*/
@TableName("user")
public class UserEntity implements Serializable
private static final long serialVersionUID = 1L;
@TableId(value = "id", type = IdType.AUTO) //表示该id为自增,新增时候不需要手动设置id。
private Integer id;
@TableField(value = "name")
private String name;
@TableField(value = "age")
private Integer age;
@TableField(value = "sex")
private String sex;
@TableField(value = "address")
private String address;
@TableField(value = "describes")
private String describes;
public String getDescribes()
return describes;
public void setDescribes(String describes)
this.describes = describes;
public Integer getId()
return id;
public void setId(Integer id)
this.id = id;
public String getName()
return name;
public void setName(String name)
this.name = name;
public Integer getAge()
return age;
public void setAge(Integer age)
this.age = age;
public String getSex()
return sex;
public void setSex(String sex)
this.sex = sex;
public String getAddress()
return address;
public void setAddress(String address)
this.address = address;
@Override
public String toString()
return this.id + " - " + this.name+ " - " +this.getSex();
1、遍历输出(forEach)
a、控制台输出每一个用户对象;
List<UserEntity> users = userService.list();
users.stream().forEach(System.out::println);
b、提取符合条件的集合第一个对象。比如提取年龄大于20且性别是男性的第一条数据。
Optional<UserEntity> user = users.stream().filter(p -> p.getAge() > 20 && p.getSex().equals("男")).findFirst();
或者写多个filter 也是可以的。
Optional<UserEntity> user = users.stream().filter(p -> p.getAge() > 20)
.filter(p -> p.getSex().equals("男"))
.findFirst();
输出如下:
2、归集(toList、toMap、toSet)
因为流不存储数据,那么在流中的数据完成处理后,需要将流中的数据重新归集到新的集合里。toList
、toSet
和toMap
比较常用,另外还有toCollection
、toConcurrentMap
等复杂一些的用法。
下面分别用一个案例演示to
List
、toMap
和toSet
:
i、比如提取List对象中的id归集到一个新集合中。怎么快速优雅?
List<Integer> ids = users.stream().map(UserEntity::getId).collect(Collectors.toList());
ii、提取对象中的两值转换成map形式;比如:name对应值sex,诸如这样:"张三":"男","李四":"女"。
Map<String, String> collect = users.stream().collect(Collectors.toMap(UserEntity::getName, UserEntity::getSex));
iii、提取符合过滤条件的对象转成set集合。
Set<UserEntity> set = users.stream().filter(p -> p.getAge() > 20).collect(Collectors.toSet());
3、排序(sorted)
i、将用户按年龄从小到大排序。
List<Integer>sortList1 = users.stream().sorted(Comparator.comparing(UserEntity::getAge)).map(UserEntity::getAge)
.collect(Collectors.toList());
ii、将用户按年龄从大到小排序。
List<Integer> sortList2 = users.stream().sorted(Comparator.comparing(UserEntity::getAge).reversed())
.map(UserEntity::getAge).collect(Collectors.toList());
4、去重(distinct)
流也可以进行合并、去重、限制、跳过等操作。
i、比如去掉重复用户;
List<UserEntity> distinctList = users.stream().distinct().collect(Collectors.toList());
好啦!两个疑问都替大家解答了,看到这里,不给赞吗?
好啦!两个疑问都替大家解答了,看到这里,不给赞吗?
好啦!两个疑问都替大家解答了,看到这里,不给赞吗?
四、往期热文推荐
- 在Ubuntu上使用IDEA搞开发是种什么体验?没想到竟是...最后有惊喜!
- 520夜我花了288大洋就得到了小师妹青睐,原因竟是...一定要看到最后!
- 你一定没用过的代码生成工具,好不好用你们说了算
- 如何实现Springboot项目保存本地系统日志文件,超详细,你值得拥有!
- 使用MultipartFile实现图片指定路径上传下载并使用postman测试教程 | 附完整源码,强烈建议收藏!
- 一篇文带你零基础玩转mysql触发器 | 超级干货,建议收藏
- ...
❤如果文章对您有所帮助,就请在文章末尾的左下角把大拇指点亮吧!(#^.^#);
❤如果喜欢bug菌分享的文章,就请给bug菌点个关注吧!(๑′ᴗ‵๑)づ╭❤~;
❤对文章有任何问题欢迎小伙伴们下方留言或者入群探讨【群号:708072830】;
❤鉴于个人经验有限,所有观点及技术研点,如有异议,请直接回复参与讨论(请勿发表攻击言论,谢谢);
❤版权声明:本文为博主原创文章,转载请附上原文出处链接和本文声明,版权所有,盗版必究!(*^▽^*).
以上是关于收藏夹吃灰系列(十四):Java8 StreamAPI的详细用法 | 开箱即用,超级详细。的主要内容,如果未能解决你的问题,请参考以下文章
收藏夹吃灰系列(十四):Java8 StreamAPI的详细用法 | 开箱即用,超级详细。
收藏夹吃灰系列:Springboot配置Thymeleaf实现静态页面访问 | 超级详细,建议收藏!
收藏夹吃灰系列:Springboot配置Thymeleaf实现静态页面访问 | 超级详细,建议收藏!