jdk1.8 新特性之Stream
---------------------
作者:码农农码一生
来源:CSDN
原文:https://blog.csdn.net/chenhao_c_h/article/details/80691284
虽然java 10已经发布,11 已经在路上,虽然 java EE 已经更名为 jakarta EE,但是大多数人连jdk1.8的新特性都不太了解,本人也是如此,所以在学习Java 8 API 添加的 Stream 的时候 做一些个人笔记,希望帮助自己的同时也能帮到大家。
首先对stream的操作可以分为两类,中间操作(intermediate operations)和结束操作(terminal operations):
中间操作总是会惰式执行,调用中间操作只会生成一个标记了该操作的新stream。
结束操作会触发实际计算,计算发生时会把所有中间操作积攒的操作以pipeline的方式执行,这样可以减少迭代次数。计算完成之后stream就会失效。
虽然大部分情况下stream是容器调用Collection.stream()方法得到的,但stream和collections有以下不同:
无存储。stream不是一种数据结构,它只是某种数据源的一个视图,数据源可以是一个数组,Java容器或I/O channel等。
为函数式编程而生。对stream的任何修改都不会修改背后的数据源,比如对stream执行过滤操作并不会删除被过滤的元素,而是会产生一个不包含被过滤元素的新stream。
惰式执行。stream上的操作并不会立即执行,只有等到用户真正需要结果的时候才会执行。
可消费性。stream只能被“消费”一次,一旦遍历过就会失效,就像容器的迭代器那样,想要再次遍历必须重新生成。
一、获取stream
// 1、数组
String[] arr = new String[]{"ab", "cd", "ef"};
Stream<String> arrStream = Arrays.stream(arr);
// 2、集合
List<String> list = Arrays.asList("ab", "cd", "ef");
Stream<String> colStream = list.stream();
// 3、值
Stream<String> stream = Stream.of("ab", "cd", "ef");
二、stream方法使用
测试数据:
List<User> list = Arrays.asList(
// name,age
new User("张三", 11),
new User("王五", 20),
new User("王五", 91),
new User("张三", 8),
new User("李四", 44),
new User("李四", 44),
new User("李四", 44)
);
1、forEach() 使用该方法迭代流中的每个数据
/**
* forEach 迭代输出每条数据.
*/
@Test
public void testForEach(){
// java 8 前
System.out.println("java 8 前");
for(User user: list){
System.out.println(user);
}
// java 8 lambda
System.out.println("java 8 lambda");
list.forEach(user -> System.out.println(user));
// java 8 stream lambda
System.out.println("java 8 stream lambda");
list.stream().forEach(user -> System.out.println(user));
}
console->
2、sorted() 使用该方法排序数据
/**
* sort 排序.
*/
@Test
public void testSort() {
System.out.println("-----排序前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----排序后-----");
// java 8 前
System.out.println("java 8 前");
Collections.sort(list, new Comparator<User>() {
@Override
public int compare(User o1, User o2) {
return o1.getAge().compareTo(o2.getAge());
}
});
for (User user : list) {
System.out.println(user);
}
// java 8 stream 方法引用
System.out.println("java 8 stream 方法引用");
list.stream().sorted(Comparator.comparing(User::getAge)).forEach(user -> System.out.println(user));
}
console->
3、filter():使用该方法过滤
/**
* filter 过滤.
*/
@Test
public void testFilter() {
// 输出年龄大于50的人
System.out.println("-----过滤前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----过滤后-----");
// java 8 前
System.out.println("java 8 前");
for(User user: list){
if (user.getAge() > 50) {
System.out.println(user);
}
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().filter((User user) -> user.getAge() > 50).forEach(user -> System.out.println(user));
}
console->
4、limit():使用该方法截断
/**
* limit 截断.
*/
@Test
public void testLimit() {
// 从第三个开始截断,只输出前三个
System.out.println("-----截断前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----截断后-----");
// java 8 前
System.out.println("java 8 前");
for (int i = 0; i < 3; i++) {
System.out.println(list.get(i));
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().limit(3).forEach(user -> System.out.println(user));
}
console->
5、skip():与limit互斥,使用该方法跳过元素
/**
* skip 跳过.
*/
@Test
public void testSkip() {
// 跳过前三个元素,从第四个开始输出
System.out.println("-----跳过前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----跳过后-----");
// java 8 前
System.out.println("java 8 前");
for (int i = 3; i < list.size(); i++) {
System.out.println(list.get(i));
}
// java 8 stream
System.out.println("java 8 stream");
list.stream().skip(3).forEach(user -> System.out.println(user));
}
console->
6、distinct():使用该方法去重,注意:必须重写对应泛型的hashCode()和equals()方法
/**
* distinct 去重.
*/
@Test
public void testDistinct() {
// 因为Arrays.asList() 返回的是Arrays的内部类ArrayList,操作remove,add会报错
List<User> users = new ArrayList(list);
// 为list去除重复数据
System.out.println("-----去重前-----");
list.forEach(user -> System.out.println(user));
System.out.println("-----去重后-----");
// java 8 前
System.out.println("java 8 前");
for (int i = 0; i < users.size() - 1; i++) {
for (int j = users.size() - 1; j > i; j--) {
if (users.get(j).getAge() == users.get(i).getAge() && users.get(j).getName()
.equals(users.get(i).getName())) {
users.remove(i);
}
}
}
for (User user : users) {
System.out.println(user);
}
// java 8 stream
System.out.println("java 8 stream");
users.stream().distinct().forEach(user -> System.out.println(user));
}
console->
***根据上述方法,完成去重+按照年龄大于40以后从小到大+只取前二
/**
* 去重+按照年龄大于40以后从小到大+只取前二
*/
@Test
public void demo() {
list.stream().distinct().filter(user -> user.getAge() > 40).sorted(
Comparator.comparing(User::getAge)).limit(2).forEach(user -> System.out
.println(user));
}
console->
7、max,min,sum,avg,count
/**
* 测试计算.
*/
@Test
public void testNum() {
IntSummaryStatistics num = list.stream().mapToInt(u -> u.getAge())
.summaryStatistics();
System.out.println("总共人数:" + num.getCount());
System.out.println("平均年龄:" + num.getAverage());
System.out.println("最大年龄:" + num.getMax());
System.out.println("最小年龄:" + num.getMin());
System.out.println("年龄之和:" + num.getSum());
}
console->
8、map():接收一个方法作为参数,该函数会被应用到每个元素上,并将其映射成一个新的元素
/**
* map 映射.
*/
@Test
public void testMap() {
// 只输出所有人的年龄
list.stream().forEach(user -> System.out.println(user));
System.out.println("映射后----->");
List<Integer> ages = list.stream().map(user -> user.getAge()).collect(toList());
ages.forEach(age -> System.out.println(age));
// 小写转大写
List<String> words = Arrays.asList("aaa", "vvvv", "cccc");
System.out.println("全部大写---->");
List<String> collect = words.stream().map(s -> s.toUpperCase()).collect(toList());
collect.forEach(s -> System.out.println(s));
}
console->
9、flatMap():对每个元素执行mapper指定的操作,并用所有mapper返回的Stream中的元素组成一个新的Stream作为最终返回结果,通俗易懂就是将原来的stream中的所有元素都展开组成一个新的stream
/**
* flatMap .
*/
@Test
public void testFlatMap() {
//创建一个 装有两个泛型为integer的集合
Stream<List<Integer>> stream = Stream.of(Arrays.asList(1, 2, 3), Arrays.asList(4, 5));
// 将两个合为一个
Stream<Integer> integerStream = stream.flatMap(
(Function<List<Integer>, Stream<Integer>>) integers -> integers.stream());
// 为新的集合
List<Integer> collect = integerStream.collect(toList());
System.out.println("新stream大小:"+collect.size());
System.out.println("-----合并后-----");
collect.forEach(o -> System.out.println(o));
}
console->
10、findFirst() :使用该方法获取第一个元素
/**
* findFirst 获取第一个元素.
*/
@Test
public void testFindFirst(){
User user = list.stream().findFirst().get();
System.out.println(user);
}
console->
jdk1.8 新特性之Stream的更多相关文章
- JDK1.8新特性之Stream类初识
JDK1.8新特性之Stream类初识 import java.util.Arrays; import java.util.List; import java.util.Optional; impor ...
- JDK1.8新特性——Stream API
JDK1.8新特性——Stream API 摘要:本文主要学习了JDK1.8的新特性中有关Stream API的使用. 部分内容来自以下博客: https://blog.csdn.net/icarus ...
- JDK1.8新特性(一) ----Lambda表达式、Stream API、函数式接口、方法引用
jdk1.8新特性知识点: Lambda表达式 Stream API 函数式接口 方法引用和构造器调用 接口中的默认方法和静态方法 新时间日期API default Lambda表达式 L ...
- JDK1.8 新特性
jdk1.8新特性知识点: Lambda表达式 函数式接口 *方法引用和构造器调用 Stream API 接口中的默认方法和静态方法 新时间日期API https://blog.csdn.net/qq ...
- jdk1.8新特性应用之Iterable
我们继续看lambda表达式的应用: public void urlExcuAspect(RpcController controller, Message request, RpcCallback ...
- JDK1.8新特性——Collector接口和Collectors工具类
JDK1.8新特性——Collector接口和Collectors工具类 摘要:本文主要学习了在Java1.8中新增的Collector接口和Collectors工具类,以及使用它们在处理集合时的改进 ...
- JDK1.8新特性之(三)--函数式接口
在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...
- JDK1.8新特性之(一)--Lambda表达式
近期由于新冠疫情的原因,不能出去游玩,只能在家呆着.于是闲来无事,开始阅读JDK1.8的源代码.在开始之前也查询了以下JDK1.8的新特性,有针对性的开始了这段旅程. 只看不操作,也是不能心领神会的. ...
- JDK1.8新特性之(二)--方法引用
在上一篇文章中我们介绍了JDK1.8的新特性有以下几项. 1.Lambda表达式 2.方法引用 3.函数式接口 4.默认方法 5.Stream 6.Optional类 7.Nashorm javasc ...
随机推荐
- 06 Linux 的常用命令
Linux 刚面世时并没有图形界面,所有的操作全靠命令完成,如 磁盘操作.文件存取.目录操作.进程管理.文件权限 设定等 在职场中,大量的 服务器维护工作 都是在 远程 通过 SSH 客户端 来完成的 ...
- OpenCV3入门(十三)图像运动模糊
1.原理 运动模糊产生: 由于相机传感器或物体相对运动, 按快门瞬间造成图像产生运动模糊. 在用摄像机获取景物图像时,如果在相机曝光期间景物和摄像机之间存在相对运动,例如用照相机拍摄快速运动的物体,或 ...
- node 微信退款
基于node 的微信退款 申请微信退款:微信退款, 1.在前端页面访问 /refund var request = require('request'); var WxPayRefund = req ...
- 简说Python之Jupyter Notebook
目录 简说Python之Jupyter Notebook 1.Jupyter Notebook 系统环境:Ubuntu 18.04.1 LTS Python使用的是虚拟环境:virutalenv Py ...
- python code practice(二):KMP算法、二分搜索的实现、哈希表
1.替换空格 题目描述:请实现一个函数,将一个字符串中的每个空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 分析: 将长度为 ...
- 二、create-react-app自定义配置
这里主要讲解添加less 和 实现Antd按需加载 首选需要执行npm run eject 暴露所有内建的配置 ,这是后面所有配置的基础,这个必须优先执行! 一.实现Antd按需加载 按需加载插件 ...
- 曹工说Spring Boot源码(23)-- ASM又立功了,Spring原来是这么递归获取注解的元注解的
写在前面的话 相关背景及资源: 曹工说Spring Boot源码(1)-- Bean Definition到底是什么,附spring思维导图分享 曹工说Spring Boot源码(2)-- Bean ...
- 【Weiss】【第03章】练习3.3:通过交换指针交换单/双链表元素
[练习3.3] 通过之调整指针(而不是数据)来交换两个相邻的元素,使用 a.单链表 b.双链表 Answer: 先放测试代码,折叠标题可以看到分别是哪种链表的测试. 实测可满足题意,但单链表和双链表的 ...
- mac redis搭建集群
1.下载redis客户端 2.修改redis.conf文件 port 6379 //端口 daemonize yes cluster-enabled yes //打开集群 cluster-config ...
- c# 自定义含有标题的容器控件(标题背景为渐变色)
1.控件效果图 此效果图中的标题颜色.字号及字体可以在控件属性中设置.标题背景的渐变色及布局内容的背景色也可以在属性中设置. 2.实现的代码(用户控件) public partial class Uc ...