JavaSE进阶(13~15)
13-Stream&File
一、Stream
1、体验Stream流 【理解】
需求: 按照下面的要求完成集合的创建和遍历
创建一个集合,存储多个字符串元素
把集合中所有以"张"开头的元素存储到一个新的集合
把"张"开头的集合中的长度为3的元素存储到一个新的集合
遍历上一步得到的集合
- 原始方式示例代码
package com.itheima.streamdemo;
public class MyStream1 {
public static void main(String[] args) {
// 集合的批量添加
ArrayList<String> list1 = new ArrayList<>(List.of("张三丰", "张无忌", "张翠山", "王二麻子", "张良", "谢广坤")); // 集合的批量添加
// list.add() //添加元素
// 遍历list1把以张开头的元素添加到list2中。
ArrayList<String> list2 = new ArrayList<>();
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流示例代码
public class StreamDemo { public static void main(String[] args) { //集合的批量添加 ArrayList<String> list1 = new ArrayList<>(List.of("张三丰","张无忌","张翠山","王二麻子","张良","谢广坤")); //Stream流 list1.stream().filter(s->s.startsWith("张")) .filter(s->s.length() == 3) .forEach(s-> System.out.println(s)); } }
2、Stream流的思想
获取方法、中间方法、终结方法
3、Stream流的三类方法 【应用】
-
获取Stream流
- 创建一条流水线,并把数据放到流水线上准备进行操作
-
中间方法
- 流水线上的操作。
- 一次操作完毕之后,还可以继续进行其他操作。
-
终结方法
- 一个Stream流只能有一个终结方法
- 是流水线上的最后一个操作
①、Stream流的获取方法
单列集合
可以使用Collection接口中的默认方法stream()生成流
default Stream<E> stream()
双列集合
间接的生成流
可以先通过keySet
或者entrySet
获取一个Set集合,再获取Stream
流
数组
Arrays中的静态方法stream 生成流
同种数据类型的多个数据
1,2,3,4,5….
“aaa”,“bbb”,“ccc”….
使用Stream.of(T…values)
生成流
代码示例:
package com.itheima.streamdemo;
/**
* 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();
}
private static void method4() {
// 同种数据类型的多个数据
Stream.of(1, 2, 3, 4, 5, 6, 7, 8).forEach(s -> System.out.println(s));
}
private static void method3() {
// 数组;
int[] arr = {
1, 2, 3, 4, 5 };
Arrays.stream(arr).forEach(s -> System.out.println(s));
}
private 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);
// 双列集合不能直接获取Stream流
// 通过keySet间接获取Stream流
// 先获取到所有的键
// 再把这个Set集合中所有的键放到Stream流中
// hm.keySet().stream().forEach(s-> System.out.println(s)); //只打印键
// 通过entrySet间接获取Stream流
// 先获取到所有的键值对对象
// 再把这个Set集合中所有的键值对对象放到Stream流中
hm.entrySet().stream().forEach(s -> System.out.println(s)); // 打印键和值
}
private 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));// 上面两行连在一起写成一行;
}
}
②、Stream流的常见中间操作方法
-
概念
中间操作的意思是,执行完此方法之后,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) )组成的流【 去除
流中重复
的元素。依赖(hashCode和equals方法】
Stream<T> filter(Predicate predicate)
:用于对流中的数据进行过滤
Predicate接口中的方法
boolean test(T t)
:对给定的参数进行判断,返回一个布尔值
- filter代码演示
package com.itheima.streamdemo;
/**
* Stream流的中间方法
*/
public class MyStream3 {
public static void main(String[] args) {
// Stream<T> filter(Predicate predicate):过滤
// Predicate接口中的方法 boolean test(T t):对给定的参数进行判断,返回一个布尔值
ArrayList<String> list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
// 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代码演示
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(s-> System.out.println(s)); System.out.println("--------"); //需求2:跳过3个元素,把剩下的元素在控制台输出 list.stream().skip(3).forEach(s-> System.out.println(s)); System.out.println("--------"); //需求3:跳过2个元素,把剩下的元素中前2个在控制台输出 list.stream().skip(2).limit(2).forEach(s-> System.out.println(s)); } }
- 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(s-> System.out.println(s)); //需求4:合并需求1和需求2得到的流,并把结果在控制台输出,要求字符串元素不能重复 Stream.concat(s1,s2).distinct().forEach(s-> System.out.println(s)); } }
③、Stream流的常见终结操作方法
-
概念
终结操作的意思是,执行完此方法之后,Stream流将不能再执行其他操作 -
常见方法
方法名 说明 void forEach(Consumer action) 对此流的每个元素执行操作 long count() 返回此流中的元素数
代码实现:
package com.itheima.streamdemo;
/**
* Stream流的终结方法
*/
public class MyStream5 {
public static void main(String[] args) {
ArrayList<String> list = new ArrayList<>();
list.add("张三丰");
list.add("张无忌");
list.add("张翠山");
list.add("王二麻子");
list.add("张良");
list.add("谢广坤");
// method1(list);
// long count():返回此流中的元素数
long count = list.stream().count();
System.out.println(count);
}
private static void method1(ArrayList<String> list) {
// void forEach(Consumer action):对此流的每个元素执行操作
// Consumer接口中的方法 void accept(T t):对给定的参数执行此操作
// 在forEach方法的底层,会循环获取到流中的每一个数据.
// 并循环调用accept方法,并把每一个数据传递给accept方法
// s就依次表示了流中的每一个数据.
// 所以,我们只要在accept方法中,写上处理的业务逻辑就可以了.
list.stream().forEach(
new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
System.out.println("====================");
// lambda表达式的简化格式
// 是因为Consumer接口中,只有一个accept方法
list.stream().forEach(
(String s) -> {
System.out.println(s);
});
System.out.println("====================");
// lambda表达式还是可以进一步简化的.
list.stream().forEach(s -> System.out.println(s));
}
}
4、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集合中
需求:过滤元素并遍历集合
定义一个集合,并添加一些整数1,2,3,4,5,6,7,8,9,10
将集合中的奇数删除,只保留偶数。
遍历集合得到2,4,6,8,10
结论:在Stream流中无法直接修改集合,数组等数据源中的数据。
代码示例:
package com.itheima.streamdemo;
/**
* Stream流的收集方法
* 练习:
* 定义一个集合,并添加一些整数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(
// (Integer i)->{
// return i % 2 == 0;
// }
// )
list.stream().filter(number -> number % 2 == 0).forEach(number -> System.out.println(number)); // 打印的偶数;
System.out.println("====================");
for (Integer integer : list) {
System.out.println(integer); // 打印的1-10的所有数据;
}
}
}
使用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集合中
- 代码实现
toSet()
和toSet()
:
package com.itheima.streamdemo;
/**
* Stream流的收集方法
* 练习:
* 定义一个集合,并添加一些整数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> list1 =<