30.Stream流
5.Stream流
5.1体验Stream流【理解】
案例需求
按照下面的要求完成集合的创建和遍历
创建一个集合,存储多个字符串元素
把集合中所有以"张"开头的元素存储到一个新的集合
把"张"开头的集合中的长度为3的元素存储到一个新的集合
遍历上一步得到的集合
原始方式示例代码
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.List;
import java.util.SortedMap; /*
* 创建一个集合,存储多个字符串元素
"张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"
把集合中所有以"张"开头的元素存储到一个新的集合 把"张"开头的集合中的长度为3的元素存储到一个新的集合 遍历上一步得到的集合
*
* */
public class MyStream1 {
public static void main(String[] args) {
ArrayList<String> list1=new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤"));
ArrayList<String> list2=new ArrayList<>();
//遍历list1把张开头的元素添加到list2中。
for (String s : list1) {
if (s.startsWith("张")) {
list2.add(s);
}
}
//遍历list2集合,把其中长度为3的元素,再添加到list3中,
ArrayList<String> list3=new ArrayList<>();
for (String s : list2) {
if (s.length() == 3) {
list3.add(s);
}
}
for (String s : list3) {
System.out.println(s);
}
//Stream流
list1.stream().filter(s -> s.startsWith("张"))
.filter(s -> s.length()==3)
.forEach(s -> System.out.println(s));
} }
Stream流的好处
直接阅读代码的字面意思即可完美展示无关逻辑方式的语义:获取流、过滤姓张、过滤长度为3、逐一打印
Stream流把真正的函数式编程风格引入到Java中
代码简洁
5.2Stream流的常见生成方式【应用】
Stream流的思想

Stream流的三类方法
获取Stream流
创建一条流水线,并把数据放到流水线上准备进行操作
中间方法
流水线上的操作
一次操作完毕之后,还可以继续进行其他操作
终结方法
一个Stream流只能有一个终结方法
是流水线上的最后一个操作
生成Stream流的方式
Collection体系集合 单列集合
使用默认方法stream()生成流, default Stream<E> stream()
Map体系集合 双列集合
把Map转成Set集合,间接的生成流、 可以先通过keySet或者entrySet获取一个Set集合,在获取Stream流
数组
通过Arrays中的静态方法stream生成流
同种数据类型的多个数据
通过Stream接口的静态方法of(T... values)生成流
- 1,2,3,4,5.......
- "aaa","bbb","ccc"......
- 使用Stream.of(T...values)生成流
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.stream.Stream;
/*
* Stream流的获取
* 单列集合:集合对象.Stream();
* 双列集合:不能直接获取,需要间接获取
* 集合对象.keySet().stream();
* 集合对象.entrySet.stream();
*数组:Arrays.stream(数组名);
* 同种数据类型的多个数据:Stream.of(数据1,数据2,数据3.。。。。)
*
* */
public class MyStream2 {
public static void main(String[] args) {
//单列集合
//method1(); //双列集合
//method2(); //数组
//method3(); //同种数据类型的多个数据
method4();
} public static void method4() {
Stream.of(1,2,3,4,5,6,7,8).forEach(s-> System.out.println(s));
} public static void method3() {
int []arr={1,2,3,4,5};
Arrays.stream(arr).forEach(s-> System.out.println(s));
} public static void method2() {
HashMap<String,Integer> hm=new HashMap<>();
hm.put("zhangsan",23);
hm.put("lisi",24);
hm.put("wangwu",25);
hm.put("zhaoliu",26);
hm.put("qianqi",27);
//双列集合不能直接获取Streatm流
//KeySet
//先获取到所有的键
//再把这个Set集合中所有的键放到Stream流中
hm.keySet().stream().forEach(s -> System.out.println(s));
//entrySet
//先获取到所有的键值对对象
//再把这个Set集合中所有的键值对对象放到Stream流中
hm.entrySet().stream().forEach(s-> System.out.println(s));
} public static void method1() {
ArrayList<String> list=new ArrayList<>();
list.add("aaa");
list.add("bbb");
list.add("ccc");
// Stream<String> stream = list.stream();
// stream.forEach(s -> System.out.println(s));
list.stream().forEach(s -> System.out.println(s));
} }
5.3Stream流中间操作方法【应用】
概念
中间操作的意思是,执行完此方法之后,Stream流依然可以继续执行其他操作
常见方法
方法名 说明 Stream<T> filter(Predicate predicate) 用于对流中的数据进行过滤 Stream<T> limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据 Stream<T> skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流 static <T> Stream<T> concat(Stream a, Stream b) 合并a和b两个流为一个流 Stream<T> distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流 filter代码演示
| Stream<T> filter(Predicate predicate) | 用于对流中的数据进行过滤 |
Predicate接口中的方法
boolean test(T t):对给定的参数进行判断,返回一个布尔值
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.List;
import java.util.function.Predicate; public class MyStream3 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
//filter方法获取流中的每一个数据
//而test方法中的s,就依次表示流中的每一个数据
//我们只要在test方法中对s进行判断就可以了,
//如果判断的结果为true,则当前的数据留下
//如果判断的结果为false,则当前的数据就不要
// list.stream().filter(
// new Predicate<String>() {
// @Override
// public boolean test(String s) {
// boolean result = s.startsWith("张");
// return result;
// }
// }
// ).forEach(s -> System.out.println(s));
//因为Predicate接口中只有一个抽象方法test
//所以我们能使用lambda表达式来简化
// list.stream().filter(
// (String s) -> {
// boolean result = s.startsWith("张");
// return result;
// }
// ).forEach(s -> System.out.println(s)); list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
}
}
limit&skip&concat&distinct代码演示
package com.itheima.streamdemo; import javax.swing.*;
import java.util.ArrayList;
import java.util.List;
import java.util.stream.Stream; public class MyStream4 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
//Stream<T> limit(long maxSize) 返回此流中的元素组成的流,截取前指定参数个数的数据
//list.stream().limit(2).forEach(s -> System.out.println(s));
//Stream<T> skip(long n) 跳过指定参数个数的数据,返回由该流的剩余元素组成的流
//list.stream().skip(2).forEach(s -> System.out.println(s));
//static <T> Stream<T> concat(Stream a, Stream b) 合并a和b两个流为一个流
ArrayList<String> list2 = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤","谢广坤","谢广坤","谢广坤","谢广坤"));
// Stream<String> stream1 = list.stream();
// Stream<String> stream2 = list2.stream();
// Stream<String> stream3 = Stream.concat(stream1, stream2);
// stream3.forEach(s -> System.out.println(s));
//Stream.concat(list.stream(),list2.stream()).forEach(s -> System.out.println(s));
//Stream<T> distinct() 返回由该流的不同元素(根据Object.equals(Object) )组成的流,依赖(hashCode和equals方法)
list.stream().distinct().forEach(s -> System.out.println(s)); }
}
5.4Stream流终结操作方法【应用】
概念
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作
常见方法
方法名 说明 void forEach(Consumer action) 对此流的每个元素执行操作
long count() 返回此流中的元素数 代码演示
| void forEach(Consumer action) |
对此流的每个元素执行操作 |
Consumer接口中的方法 void accept(T t):对给定的参数执行此操作
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.List;
import java.util.function.Consumer; public class MyStream5 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤"));
//void forEach(Consumer action)对此流的每个元素执行操作
//Consumer接口中的方法 void accept(T t):对给定的参数执行此操作
//method1(list);
// long count()返回此流中的元素数
long count = list.stream().count();
System.out.println(count);
} public static void method1(ArrayList<String> list) {
//在forEach方法的底层 ,会循环获取到流中的每一个数据
//并循环调用accept方法,并把每一个数据传递给accept方法
//s就依次表示了流中的每一个数据
//所以,我们只要在accept方法中,写上处理的业务逻辑就可以了
list.stream().forEach(
new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
}
);
//lambda表达式的简化格式
//是因为Consumer接口中,只有一个accept方法
list.stream().forEach(s -> System.out.println(s));
}
}
需求:过滤元素并遍历集合
定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
将集合中的奇数删除,只保留偶数
遍历集合得到2,4,6,8,10
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.List; /*
*需求:过滤元素并遍历集合 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10 将集合中的奇数删除,只保留偶数 遍历集合得到2,4,6,8,10
*
*
* */
public class MyStream6 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
list.stream().filter(number -> number%2==0).forEach(number-> System.out.println(number));
System.out.println("==============");
for (Integer integer : list) {
System.out.println(integer);
}
}
}
结论:在Stream流中无法直接修改集合,数组等数据源中的数据
5.5Stream流的收集操作【应用】
使用Stream流的方式操作完毕之后,我想把流中的数据保存起来,该怎么办
概念
对数据使用Stream流的方式操作完毕后,可以把流中的数据收集到集合中
常用方法
方法名 说明 R collect(Collector collector) 把结果收集到集合中 工具类Collectors提供了具体的收集方式
方法名 说明 public static <T> Collector toList() 把元素收集到List集合中 public static <T> Collector toSet() 把元素收集到Set集合中 public static Collector toMap(Function keyMapper,Function valueMapper) 把元素收集到Map集合中 代码演示
- 收集到list和set单列集合中
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors; /*
*需求:过滤元素并遍历集合 定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10 将集合中的奇数删除,只保留偶数 遍历集合得到2,4,6,8,10
*
*
* */
public class MyStream7 {
public static void main(String[] args) {
ArrayList<Integer> list = new ArrayList<>();
for (int i = 1; i <= 10; i++) {
list.add(i);
}
list.add(10);
list.add(10);
list.add(10);
list.add(10);
list.add(10);
//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);
}
}
收集到双列集合中
练习:
创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄
”zhangsan“,23
”lisi“,24
”wangwu“,25
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
public static Collector toMap(Function keyMap,Function valueMapper):把元素收集到Map集合中
package com.itheima.streamdemo; import java.util.ArrayList;
import java.util.Map;
import java.util.stream.Collectors; /*
* 创建一个ArrayList集合,并添加以下字符串,字符串中前面是姓名,后面是年龄 ”zhangsan“,23
”lisi“,24
”wangwu“,25
保留年龄大于等于24岁的人,并将结果收集到Map集合中,姓名为键,年龄为值
*
* */
public class MyStream8 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("zhangsan,23");
list.add("lisi,24");
list.add("wangwu,25"); Map<String, Integer> map = list.stream().filter(
s -> {
String[] split = s.split(",");
int age = Integer.parseInt(split[1]);
return age >= 24;
}
//collection方法只能获取到流中剩余的每一个数据
//在底层不能创建容器,也不能把数据添加到容器当中 //Collectors.toMap 创建一个集合,并将数据添加到集合当中 //s依次表示流中的每一个数据 //第一个lambda表达式就是如何获取到map中的键
//第二个lambda表达式就是如何获取到map中的值
).collect(Collectors.toMap(
s -> s.split(",")[0],
s -> Integer.parseInt(s.split(",")[1])));
System.out.println(map);
}
}
5.6Stream流综合练习【应用】
案例需求
现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
男演员只要名字为3个字的前两人
女演员只要姓杨的,并且不要第一个
把过滤后的男演员姓名和女演员姓名合并到一起
把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
演员类Actor已经提供,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
代码实现
演员类
package com.itheima.streamdemo;
public class Actor {
private String name;
public Actor() {
}
public Actor(String name) {
this.name = name;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
@Override
public String toString() {
return "Actor{" +
"name='" + name + '\'' +
'}';
}
}
测试类
package com.itheima.streamdemo; import javax.xml.namespace.QName;
import java.util.ArrayList;
import java.util.stream.Stream; /**
* 现在有两个ArrayList集合,分别存储6名男演员名称和6名女演员名称,要求完成如下的操作
* 1.男演员只要名字为3个字的前两人
* 2.女演员只要姓杨的,并且不要第一个
* 3.把过滤后的男演员姓名和女演员姓名合并到一起
* 4.把上一步操作后的元素作为构造方法的参数创建演员对象,遍历数据
* 演员类Actor,里面有一个成员变量,一个带参构造方法,以及成员变量对应的get/set方法
*/
public class MyStream9 {
public static void main(String[] args) {
ArrayList<String> manList = new ArrayList<>();
manList.add("张国立");
manList.add("张晋");
manList.add("刘烨");
manList.add("郑伊健");
manList.add("徐峥");
manList.add("王宝强"); ArrayList<String> womanList = new ArrayList<>();
womanList.add("郑爽");
womanList.add("杨紫");
womanList.add("关晓彤");
womanList.add("张天爱");
womanList.add("杨幂");
womanList.add("赵丽颖");
//男演员只要名字为3个字的前两个人
Stream<String> stream1=manList.stream().filter(name -> name.length() == 3).limit(2);
//女演员只要姓杨的,并且不要第一个
Stream<String> stream2=womanList.stream().filter(name-> name.startsWith("杨")).skip(1); Stream.concat(stream1,stream2).forEach(name->{
Actor actor = new Actor(name);
System.out.println(actor);
});
} }
30.Stream流的更多相关文章
- 【重学Java】Stream流
Stream流 体验Stream流[理解] 案例需求 按照下面的要求完成集合的创建和遍历 创建一个集合,存储多个字符串元素 把集合中所有以"张"开头的元素存储到一个新的集合 把&q ...
- 乐字节-Java8新特性-接口默认方法之Stream流(下)
接上一篇:<Java8新特性之stream>,下面继续接着讲Stream 5.流的中间操作 常见的流的中间操作,归为以下三大类:筛选和切片流操作.元素映射操作.元素排序操作: 操作 描述 ...
- 简洁方便的集合处理——Java 8 stream流
背景 java 8已经发行好几年了,前段时间java 12也已经问世,但平时的工作中,很多项目的环境还停留在java1.7中.而且java8的很多新特性都是革命性的,比如各种集合的优化.lambda表 ...
- Java8新特性 Stream流式思想(一)
遍历及过滤集合中的元素使用传统方式遍历及过滤集合中的元素package cn.com.zq.demo01.Stream.test01.Stream; import java.util.ArrayLis ...
- Java8新特性 Stream流式思想(三)
Stream接口中的常用方法 forEach()方法package cn.com.cqucc.demo02.StreamMethods.Test02.StreamMethods; import jav ...
- 2020你还不会Java8新特性?方法引用详解及Stream 流介绍和操作方式详解(三)
方法引用详解 方法引用: method reference 方法引用实际上是Lambda表达式的一种语法糖 我们可以将方法引用看作是一个「函数指针」,function pointer 方法引用共分为4 ...
- 再来看看Java的新特性——Stream流
半年前开始试着使用Java的新特性,给我印象最深的就是Stream流和Optional.其中Stream提高了看法效率,让代码看起来十分清爽. 为什么要使用流? 摘要中已经说明了,为了提高开发效率.流 ...
- 详解 stream流
在本人之前的博文中,我们学习了 I/O流.NIO流的相关概念. 那么,在JDK8的更新内容中,提出了一个新的流 -- stream流 那么,现在,本人就来讲解下这个流: 目录 stream流 常用AP ...
- 第十章 函数式接口&Stream流
10.1.函数式接口 10.1.1.概述 有且仅有一个抽象方法的接口,并且可以通过在类上标注@FunctionalInterface注解进行检测,建议自定义的函数式接口都加上这个注解 10.1.2.函 ...
随机推荐
- 什么是一致性hash?
一致性hash 前言 说出来大家可能不相信,我昨天做梦梦到自己在面试,然后面试官问了我这个问题哈哈~然后我就打算按照自己的理解写一写.如果有写的不对的欢迎大家指正! 直接开始 普通hash算法 普通h ...
- Ansible 教程
[注]本文译自:https://www.edureka.co/blog/ansible-tutorial/ 在阅读本文之前,你应该已经知道,Ansible 构成了 DevOps 认证的关键部分,它 ...
- Dapper, Ef core, Freesql 插入大量数据性能比较(一)
需求:导入9999行数据时Dapper, Ef core, Freesql 谁的性能更优,是如何执行的,级联增加谁性能更佳. 确认方法:sql server 的 sys.dm_exec_query_s ...
- ES系列(二):基于多播的集群发现实现原理解析
ES作用超强悍的搜索引擎,除了需要具有齐全的功能支持,超高的性能,还必须要有任意扩展的能力.一定程度上,它是一个大数据产品.而要做扩展性,集群自然少不了.然而单独的集群又是不够的,能够做的事情太少,所 ...
- JVM(一)内存结构
今日开篇 什么是JVM 定义 Java Virtual Machine,JAVA程序的运行环境(JAVA二进制字节码的运行环境) 好处 一次编写,到处运行 自动内存管理,垃圾回收机制 数组下标越界检查 ...
- pycharm pymysql连接mysql 报错 pymysql.err.InterfaceError: (0, '')
pycharm pymysql连接mysql 执行MySQL操作遇到以下报错信息: conn.query(q) File "C:\Software\Python37\lib\site-p ...
- 浅入Kubernetes(11):了解 Service 和 Endpoint
目录 Srevice Service 的创建及现象 Service 定义 Endpoint slices 创建 Endpoint.Service Service 创建应用 创建 Endpoint 浅入 ...
- Day11_49_HashTable
HashTable * HashTable是较早期的使用Hash算法的一种容器结构,现在基本已被淘汰,单线程多使用HashMap,多线程使用ConcurrentHashMap. * HashTable ...
- Mediapipe 在RK3399PRO上的初探(二)(自定义Calculator)
PS:要转载请注明出处,本人版权所有. PS: 这个只是基于<我自己>的理解, 如果和你的原则及想法相冲突,请谅解,勿喷. 前置说明 本文作为本人csdn blog的主站的备份.(Bl ...
- springboot的logback的配置文件
之前敲出来一个 logback 的配置文件,防止以后找起来麻烦在这里存个档 修改了日志输出的内容 设置默认级别为 INFO 正常日志 ( TRACE 到 WARN ) 输出到单独的文件夹 异常日志 ( ...