【重学Java】Stream流
Stream流
体验Stream流【理解】
案例需求
按照下面的要求完成集合的创建和遍历
- 创建一个集合,存储多个字符串元素
- 把集合中所有以"张"开头的元素存储到一个新的集合
- 把"张"开头的集合中的长度为3的元素存储到一个新的集合
- 遍历上一步得到的集合
原始方式示例代码
public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>(); list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌"); //把集合中所有以"张"开头的元素存储到一个新的集合
ArrayList<String> zhangList = new ArrayList<String>(); for(String s : list) {
if(s.startsWith("张")) {
zhangList.add(s);
}
} // System.out.println(zhangList); //把"张"开头的集合中的长度为3的元素存储到一个新的集合
ArrayList<String> threeList = new ArrayList<String>(); for(String s : zhangList) {
if(s.length() == 3) {
threeList.add(s);
}
} // System.out.println(threeList); //遍历上一步得到的集合
for(String s : threeList) {
System.out.println(s);
}
System.out.println("--------"); //Stream流来改进
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s)); }
}
Stream流的好处
- 直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印
- Stream流把真正的函数式编程风格引入到Java中
- 代码简洁
Stream流的常见生成方式【应用】
- Stream流的思想
Stream流的三类方法
- 获取Stream流
- 创建一条流水线,并把数据放到流水线上准备进行操作
- 中间方法
- 流水线上的操作
- 一次操作完毕之后,还可以继续进行其他操作
- 终结方法
- 一个Stream流只能有一个终结方法
- 是流水线上的最后一个操作
- 获取Stream流
生成Stream流的方式
Collection体系集合(单列集合)
使用默认方法stream()生成流, default Stream stream()
Map体系集合(双列集合)
把Map转成Set集合,间接的生成流
数组
通过Arrays中的静态方法stream生成流
同种数据类型的多个数据
通过Stream接口的静态方法of(T... values)生成流
代码演示
public class StreamDemo {
public static void main(String[] args) {
//Collection体系的集合可以使用默认方法stream()生成流
List<String> list = new ArrayList<String>();
Stream<String> listStream = list.stream(); Set<String> set = new HashSet<String>();
Stream<String> setStream = set.stream(); //Map体系的集合间接的生成流
Map<String,Integer> map = new HashMap<String, Integer>();
Stream<String> keyStream = map.keySet().stream();
Stream<Integer> valueStream = map.values().stream();
Stream<Map.Entry<String, Integer>> entryStream = map.entrySet().stream(); //数组可以通过Arrays中的静态方法stream生成流
String[] strArray = {"hello","world","java"};
Stream<String> strArrayStream = Arrays.stream(strArray); //同种数据类型的多个数据可以通过Stream接口的静态方法of(T... values)生成流
Stream<String> strArrayStream2 = Stream.of("hello", "world", "java");
Stream<Integer> intStream = Stream.of(10, 20, 30);
}
}
Stream流中间操作方法【应用】
概念
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作
常见方法
方法名 说明 Stream filter(Predicate predicate) 用于对流中的数据进行过滤 Stream limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据 Stream skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 static Stream concat(Stream a, Stream b) 合并a和b两个流为一个流 Stream distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流(自定义数据类型重写equals和hashCode) filter原理
ArrayList list = new ArrayList(List.of(1,2,3,4));
list.stream().filter(new Predicate() {
@Override
public boolean test(Object o) {
return false;
}
});
//Predicate中有一个抽象方法test可以使用匿名内部类或者lambda表达式
//filter方法获取流中的每一个数据
//而test中的s,依次表示流中的每一个数据
//我们只需要在流中对s进行判断就行了
//如果判断结果为true,则当前结果留下
//如果判断结果为false,则当前结果不要
filter代码演示
public class StreamDemo01 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>(); list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌"); //需求1:把list集合中以张开头的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
System.out.println("--------"); //需求2:把list集合中长度为3的元素在控制台输出
list.stream().filter(s -> s.length() == 3).forEach(System.out::println);
System.out.println("--------"); //需求3:把list集合中以张开头的,长度为3的元素在控制台输出
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(System.out::println);
}
}
limit&skip代码演示
public class StreamDemo02 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>(); list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌"); //需求1:取前3个数据在控制台输出
list.stream().limit(3).forEach(System.out::println);
System.out.println("--------"); //需求2:跳过3个元素,把剩下的元素在控制台输出
list.stream().skip(3).forEach(System.out::println);
System.out.println("--------"); //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出
list.stream().skip(2).limit(2).forEach(System.out::println);
}
}
concat&distinct代码演示
public class StreamDemo03 {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>(); list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌"); //需求1:取前4个数据组成一个流
Stream<String> s1 = list.stream().limit(4); //需求2:跳过2个数据组成一个流
Stream<String> s2 = list.stream().skip(2); //需求3:合并需求1和需求2得到的流,并把结果在控制台输出
// Stream.concat(s1,s2).forEach(System.out::println); //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复
Stream.concat(s1,s2).distinct().forEach(System.out::println);
}
}
Stream流终结操作方法【应用】
概念
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作
常见方法
方法名 说明 void forEach(Consumer action) 获取流的每个元素并对其执行操作 long count() 返回此流中的元素数 代码演示
public class StreamDemo {
public static void main(String[] args) {
//创建一个集合,存储多个字符串元素
ArrayList<String> list = new ArrayList<String>(); list.add("林青霞");
list.add("张曼玉");
list.add("王祖贤");
list.add("柳岩");
list.add("张敏");
list.add("张无忌"); //需求1:把集合中的元素在控制台输出
//list.stream().forEach(System.out::println); //list.stream().forEach(new Consumer() {
// @Override
// public void accept(Object o) {
//
// }
// });
//在forEach方法底层会循环调用流中每一个数据
//并循环调用accept方法,把每一个数据传递给accept方法
//s就依次代表流中的每一个数据
//所以只需要在accept方法中编写相应的业务逻辑即可 //需求2:统计集合中有几个以张开头的元素,并把统计结果在控制台输出
long count = list.stream().filter(s -> s.startsWith("张")).count();
System.out.println(count);
}
}
Stream流的收集操作【应用】
概念
对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中
常用方法
方法名 说明 R collect(Collector collector) 把结果收集到集合中 工具类Collectors提供了具体的收集方式
方法名 说明 public static Collector toList() 把元素收集到List集合中 public static Collector toSet() 把元素收集到Set集合中 public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中 代码演示
- 单列集合
ArrayList<Integer> list = new ArrayList<Integer>(List.of(1, 2, 3, 4,4,4)); //filter负责过滤数据
//collect负责收集数据
//获取流中剩余的数据,但是他不负责创建容器,也不负责把数据添加到容器中
//Collectors.toList()会在底层创建一个List集合,并把所以的数据添加到List集合中。 List<Integer> list1 = list.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());
System.out.println(list1); Set<Integer> set = list.stream().filter(number -> number % 2 == 0).collect(Collectors.toSet());
System.out.println(set);
//[2, 4, 4, 4]
//[2, 4]
- 双列集合
public static void main(String[] args) {
/**
* Steam流的收集方法
*
* 创建一个ArrayList集合,并添加以下的字符串,字符串中前面是姓名,后面是年龄
* "zhangsan,23"
* "lisi,24"
* "wangwu,25"
* 保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
*/
ArrayList<String> list = new ArrayList<>(List.of("zhangsan,23","lisi,24","wangwu,25"));
Map<String,Integer> map = list.stream().filter((String s)->{
String[] split = s.split(",");
int i = Integer.parseInt(split[1]);
return i>=24;
}).collect(Collectors.toMap(
(String s)-> {
return s.split(",")[0];
},
(String s)->{
return Integer.valueOf(s.split(",")[1]);
}
));
map.forEach((String s,Integer i)->{
System.out.println(s+"---"+i);
});
}
Stream流综合练习【应用】
- 案例需求
代码实现
演员类
public class Actor {
private String name; public Actor(String name) {
this.name = name;
} public String getName() {
return name;
} public void setName(String name) {
this.name = name;
}
}
测试类
package com.cnblogs.gonghr;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Collectors;
import java.util.stream.Stream; public class test13 {
public static void main(String[] args) {
String actor_man_one = "周润发";
String actor_man_two = "成龙";
String actor_man_three = "刘德华";
String actor_man_four = "吴京";
String actor_man_five = "周星驰";
String actor_man_six = "李连杰";
ArrayList<String> actors_man = new ArrayList<>(List.of(actor_man_one, actor_man_two, actor_man_three, actor_man_four, actor_man_five, actor_man_six));
String actor_woman_one = "林心如";
String actor_woman_two = "张曼玉";
String actor_woman_three = "杨超越";
String actor_woman_four = "林志玲";
String actor_woman_five = "周冬雨";
String actor_woman_six = "杨颖";
ArrayList<String> actors_woman = new ArrayList<>(List.of(actor_woman_one, actor_woman_two, actor_woman_three, actor_woman_four, actor_woman_five, actor_woman_six));
Stream<String> actorStream_man= actors_man.stream().filter(actor -> actor.length() == 3).limit(2);
Stream<String> actorStream_woman = actors_woman.stream().filter(actor -> actor.startsWith("杨")).skip(1);
Stream.concat(actorStream_man, actorStream_woman).forEach(s->{
Actor actor = new Actor(s);
System.out.println(actor);
});
}
}
//Actor{name='周润发'}
//Actor{name='刘德华'}
//Actor{name='杨颖'}
【重学Java】Stream流的更多相关文章
- 重学 Java 设计模式:实战装饰器模式(SSO单点登录功能扩展,增加拦截用户访问方法范围场景)
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 对于代码你有编程感觉吗 很多人写代码往往是没有编程感觉的,也就是除了可以把功能按照固 ...
- 重学 Java 设计模式:实战状态模式「模拟系统营销活动,状态流程审核发布上线场景」
作者:小傅哥 博客:https://bugstack.cn - 原创系列专题文章 沉淀.分享.成长,让自己和他人都能有所收获! @ 目录 一.前言 二.开发环境 三.状态模式介绍 四.案例场景模拟 1 ...
- 12天,这本《重学Java设计模式》PDF书籍下载量9k,新增粉丝1400人,Github上全球推荐榜!
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言
- 重学Java(一):与《Java编程思想》的不解之缘
说起来非常惭愧,我在 2008 年的时候就接触了 Java,但一直到现在(2018 年 10 月 10 日),基础知识依然非常薄弱.用一句话自嘲就是:十年 IT 老兵,Java 菜鸡一枚. 于是,我想 ...
- 一文带你入门Java Stream流,太强了
两个星期以前,就有读者强烈要求我写一篇 Java Stream 流的文章,我说市面上不是已经有很多了吗,结果你猜他怎么说:"就想看你写的啊!"你看你看,多么苍白的喜欢啊.那就&qu ...
- 重学 Java 设计模式:实战抽象工厂模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获!
- 重学 Java 设计模式:实战单例模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 5个创建型模式的最后一个 在设计模式中按照不同的处理方式共包含三大类:创建型模式.结 ...
- 重学 Java 设计模式:实战适配器模式
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 擦屁屁纸80%的面积都是保护手的! 工作到3年左右很大一部分程序员都想提升自己的技术 ...
- 重学 Java 设计模式:实战桥接模式(多支付渠道「微信、支付宝」与多支付模式「刷脸、指纹」场景)
作者:小傅哥 博客:https://bugstack.cn - 编写系列原创专题文章 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 为什么你的代码那么多ifelse 同类的业务.同样的功能, ...
- 重学 Java 设计模式:实战外观模式「基于SpringBoot开发门面模式中间件,统一控制接口白名单场景」
作者:小傅哥 博客:https://bugstack.cn 沉淀.分享.成长,让自己和他人都能有所收获! 一.前言 你感受到的容易,一定有人为你承担不容易 这句话更像是描述生活的,许许多多的磕磕绊绊总 ...
随机推荐
- 关于C语言的指针数组与指针数组的个人理解
一.指针数组与指针数组 1,指针数组 顾名思义,即一个元素全部是指针的数组,其形式与普通数组相似,形式如 *a[N]. 在理解指针数组的使用方式前,我先来说下我个人对数组的理解. 比如一维整形数组(形 ...
- 并发王者课-青铜5:一探究竟-如何从synchronized理解Java对象头中的锁
在前面的文章<青铜4:synchronized用法初体验>中,我们已经提到锁的概念,并指出synchronized是锁机制的一种实现.可是,这么说未免太过抽象,你可能无法直观地理解锁究竟是 ...
- (xxx) is not defined at HTMLInputElement.onblur(Day_27)
错误: 这个报错我当时是卡了很久,方法是肯定没有问题的,但js所有的事件都失效了. 解决方案: 1.检查js命名是否有误,若外部引用js文件,尽量使用全小写命名,遵守js命名规范. 2.若还不行,请将 ...
- Go基础结构与类型05---程序运算
package main import ( "fmt" "math" ) func main() { /*加减乘除,求余*/ fmt.Println(" ...
- Tengine Framework基础
Tengine Framework基础 最受开发者喜爱的边缘AI计算框架 Tengine是OPEN AI LAB推出的自主知识产权的边缘AI计算框架,致力于解决AIoT产业链碎片化问题,加速AI产业化 ...
- TensorFlow优化器及用法
TensorFlow优化器及用法 函数在一阶导数为零的地方达到其最大值和最小值.梯度下降算法基于相同的原理,即调整系数(权重和偏置)使损失函数的梯度下降. 在回归中,使用梯度下降来优化损失函数并获得系 ...
- CUDA 9中张量核(Tensor Cores)编程
CUDA 9中张量核(Tensor Cores)编程 Programming Tensor Cores in CUDA 9 一.概述 新的Volta GPU架构的一个重要特点是它的Tensor核,使T ...
- Java IO学习笔记三:MMAP与RandomAccessFile
作者:Grey 原文地址:Java IO学习笔记三:MMAP与RandomAccessFile 关于RandomAccessFile 相较于前面提到的BufferedReader/Writer和Fil ...
- 性能监控之常见 Java Heap Dump 方法
一.前言 在本文中,我们总结下抓 Java dump 的几种不同方法. Java Heap Dump 是特定时刻 JVM 内存中所有对象的快照.它们对于解决内存泄漏问题和分析 Java 应用程序中的内 ...
- NX二次开发-获取WCS坐标系的原点坐标和矩阵标识
函数:UF_CSYS_ask_csys_info() 函数说明:获取工作坐标系对象的标识符. 用法: #include <uf.h> #include <uf_csys.h> ...