文章目录
Java进阶【十二期】
一、集合进阶 - 不可变集合
1. 创建不可变集合
1. list不可变集合的创建
2. set不可变集合的创建
3. map不可变集合的创建和注意事项
4. map 集合 拓展容量
小结
Stream流
一、什么是 stream流
二、 stream流的使用步骤
stream 流水线 的使用
1. 单列集合使用 stream 流水线
package com.liujintao1.stream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class StreamDemo {
public static void main(String[] LiuJinTao) {
/*
- 单列集合操作 stream 流
*/
ArrayList<String> list = new ArrayList<>();
// 批量添加数据
Collections.addAll(list, "a", "b", "c", "d", "e");
// 一、
// 1. 获取 stream 流水线
Stream<String> stream1 = list.stream();
// 2. 将流水线通过匿名内部类进行打印
stream1.forEach(new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
});
// 二、
// 2. 获取 stream 流水线 并且打印 (一行代码搞定)
list.stream().forEach(string -> System.out.println(string)); // a b c d e
}
}
2 . 双列集合 使用 stream 流水线
package com.liujintao1.stream;
import java.util.HashMap;
import java.util.Map;
import java.util.Set;
import java.util.function.Consumer;
import java.util.stream.Stream;
public class StreamDemo2 {
public static void main(String[] LiuJinTao) {
/*
- 双列集合 使用 stream 流
*/
Map<String, Integer> hm = new HashMap<>();
hm.put("张三", 23);
hm.put("李四", 24);
hm.put("王五", 25);
hm.put("赵六", 26);
hm.put("孙七", 27);
System.out.println(hm);
// 1. 双列集合使用 stream 流,先转为单列集合
Set<Map.Entry<String, Integer>> set = hm.entrySet();
// 方法一;匿名内部类
// 2. 然后使用单列集合获取 stream 流
Stream<Map.Entry<String, Integer>> stream1 = set.stream();
stream1.forEach(new Consumer<Map.Entry<String, Integer>>() {
@Override
public void accept(Map.Entry<String, Integer> stringIntegerEntry) {
System.out.println(stringIntegerEntry);
}
});
System.out.println("--------------------------------");
// 方法二;Lambda表达式直接一步到位
set.stream().forEach( s -> System.out.println(s));
}
}
3. 数组使用 stream 流水线
package com.liujintao1.stream;
import java.util.Arrays;
import java.util.stream.Stream;
public class StreamDemo3 {
public static void main(String[] LiuJinTao) {
/*
- 数组使用 stream 流
*/
// 创建两个不同类型的集合
int [] intArr = {1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
String[] StringArr = {"a", "b", "c", "d", "e"};
// 2. 通过Arrays 获取 stream 流水线
Arrays.stream(intArr).forEach(item -> System.out.println(item));
System.out.println("---------------------------------------");
Arrays.stream(StringArr).forEach(item -> System.out.println(item));
}
}
4. 一对零散数据使用 stream 流水线
// 一对零散的数据使用 stream 流水线
// Stream.of 方法,可以传递一堆数据也可以传递数组,但是数组必须是引用数据类型的。如果不是则会 装箱 到 Stream 中 输出地址
System.out.println("---------------------------------------");
Stream.of(1,2,3,4,6,7,8,9,10).forEach(item -> System.out.println(item));
二、Stream 流 - 中间方法
filter方法
public class StreamDemo04 {
/**
* stream中间方法 - filter 过滤方法
* @param LiuJinTao
*/
public static void main(String[] LiuJinTao) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明", "张晓兰", "张志强", "张浩宇", "张风", "张云", "李娜", "王磊", "赵敏", "刘涛");
// 使用 stream 流 过滤所有姓张的姓名,并且长度为三的姓名。
list.stream().filter( item -> item.startsWith("张")).forEach( item -> { if (item.length() == 3) { System.out.println(item); } });
System.out.println("-=---------------------------------");
for (String i : list) {
System.out.println(i); // stream操作玩不会印象原来的数据
}
}
limit方法
/**
* Stream中间方法 - limit 获取前几个元素
*/
public static void main(String[] LiuJinTao) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明", "张晓兰", "张志强", "张浩宇", "张风", "张云", "李娜", "王磊", "赵敏", "刘涛");
// 需求:使用limit截取非姓张姓名的前两位姓名
list.stream().filter(item -> !item.startsWith("张")).limit(2).forEach(item -> System.out.println(item) ); // "李娜", "王磊"
skip方法
public class StreamDemo06 {
/**
* stream流方法中的中间方法 - skip 跳过前几个元素
*/
public static void main(String[] LiuJinTao) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明", "张晓兰", "张志强", "张浩宇", "张风", "张云", "李娜", "王磊", "赵敏", "刘涛");
// 使用 stream中间方法 输出 姓名为;张风 以及之后的所有的姓名
list.stream().skip(4).forEach( item -> System.out.println(item));
}
distinct方法
public class StreamDemo08 {
/**
* stream 流的 distinct 元素去重
*/
public static void main(String[] LiuJinTao) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明", "张伟明", "张伟明", "张晓兰", "张志强", "张浩宇", "张风", "张云", "李娜", "王磊", "赵敏", "刘涛");
// stream 流 去重, 三个 "张伟明" ,保留一个
list.stream().distinct().forEach( item -> System.out.println(item) );
}
concat
public class StreamDemo07 {
/**
* stream 流的 concat 中间方法 流的合并
*/
public static void main(String[] LiuJinTao) {
ArrayList<String> list1 = new ArrayList<>();
Collections.addAll(list1, "张伟明", "张晓兰", "张志强", "张浩宇", "张风", "张云", "李娜", "王磊", "赵敏", "刘涛");
ArrayList<String> list2 = new ArrayList<>();
Collections.addAll(list2, "asdf", "safgs", "gesa");
// 将两个流进行合并
Stream.concat(list1.stream(), list2.stream()).forEach( item -> System.out.println(item));
}
map 方法
public class StreamDemo09 {
/**
* stream 流 map 流的数据转换
*/
public static void main(String[] LiuJinTao) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明-12", "张晓兰-13", "张志强-14", "张浩宇-15", "张风-16", "张云-17", "李娜-18", "王磊-19", "赵敏-20", "刘涛-21");
// 取出集合中每个元素的数字,并且输出
list.stream().map( item -> Integer.parseInt(item.split("-")[1])).forEach( item -> System.out.println(item) );
}
三、 stream 流 - 终结方法
forEach 方法
/**
* forEach方法 遍历
*/
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明-12", "张晓兰-13", "张志强-14", "张浩宇-15", "张风-16", "张云-17", "李娜-18", "王磊-19", "赵敏-20", "刘涛-21");
// 使用 forEach 方法进行遍历
list.stream().forEach( item -> System.out.println(item) );
/**
* 遍历结果如下:
* 张伟明-12
* 张晓兰-13
* 张志强-14
* 张浩宇-15
* 张风-16
* 张云-17
* 李娜-18
* 王磊-19
* 赵敏-20
* 刘涛-21
*/
}
count 方法
/**
* count方法的演示
* @param LiuJinTao
*/
public static void main(String [] LiuJinTao) {
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明-12", "张晓兰-13", "张志强-14", "张浩宇-15", "张风-16", "张云-17", "李娜-18", "王磊-19", "赵敏-20", "刘涛-21");
// 使用 count 方法 统计 list 结合中 数据的个数
long result = list.stream().count();
System.out.println(result);
/**
* 运行结果:
* - 10
*/
}
toArray 方法
/**
* toArray 方法的演示
*/
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张伟明", "张晓兰", "张志强", "张浩宇", "张风", "张云", "李娜", "王磊", "赵敏", "刘涛");
String[] array = list.stream().toArray(value -> new String[value]);
System.out.println(Arrays.toString(array));
collector 方法
-
list集合
-
set集合
-
注意set去重,所以,list和set都是收集到集合中,唯一的不同就是set可以去重。
-
map集合
匿名内部类实现方法:
Lambda表达式实现:
stream 流 总结
Stream 流 - 练习一、
代码示例:
public static void main(String[] LiuJinTao) {
ArrayList<Integer> list = new ArrayList<>();
Collections.addAll(list, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10);
// 过滤奇数,保留偶数
List<Integer> collectList = list.stream().filter(number -> number % 2 == 0).collect(Collectors.toList());
System.out.println(collectList);
/**
* - 运行结果:
* [2, 4, 6, 8, 10]
*/
}
stream 流 - 练习二、
代码示例:
public static void main(String[] LiuJinTao) {
// 1. 创建集合并添加数据
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "zhangsan, 23", "lisi, 24", "wangwu, 25");
// 2. 过滤年龄大于 24 岁的人 (注意切割的时候添加空格,以为集合添加的时候我们逗号后面使用了空格)
Map<String, Integer> collctMap = list.stream().filter(item -> Integer.parseInt(item.split(", ")[1]) >= 24).collect(Collectors.toMap(
s -> s.split(", ")[0], // 键的规则
s -> Integer.parseInt(s.split(", ")[1]) // 值的规则
));
System.out.println(collctMap);
/**
* 输出结果:
* - {lisi=24, wangwu=25}
*/
}
Stram 流 - 练习三、
代码示例:
public class StreamTest3 {
public static void main(String[] LiuJinTao ){
// 1. 创建两个数据集合,并添加数据
ArrayList<String> actorList = new ArrayList<>();
ArrayList<String> actressList = new ArrayList<>();
Collections.addAll(actorList, "刘坤坤,24", "叶小城,23", "刘不住,22", "吴签,24", "谷歌,30", "肖凉凉,27");
Collections.addAll(actressList, "赵小英,35", "杨莹,36", "高原呀,43", "张田田,31", "刘仟,35", "杨小米,33");
// 2. 将男演员 名字长度为 三 的演员姓名 过滤,取前两个
Stream<String> stream1 = actorList.stream().filter(item -> item.split(",")[0].length() == 3).limit(2);
// 3. 过滤出 性杨的女演员姓名, 取出第一个
Stream<String> stream2 = actressList.stream().filter(item -> item.startsWith("杨")).skip(1);
// 4. 将过滤后的 男演员 和 女演员 合并到 一起, 同时将该集合分装到 Actor对象中(字符串转为自定义对象类型,使用 map 进行数据转换)
// 5. 将演员对象保存到 List 结合中
List<Actor> actor = Stream.concat(stream1, stream2).map(item -> new Actor(item.split(",")[0], Integer.parseInt(item.split(",")[1]))).collect(Collectors.toList());
System.out.println(actor);
// 5. 将演员对象保存到 List 结合中 (分开写发如下也是一样的)
// List<Actor> collectList = actor.stream().collect(Collectors.toList());
// System.out.println(collectList);
}
/**
* 输出结果为:
* - [Actor{name = 刘坤坤, age = 24}, Actor{name = 叶小城, age = 23}, Actor{name = 杨小米, age = 33}]
*/
}
方法引用
一、 什么是 方法引用
二、方法引用的分类
1,引用静态方法
2. 引用成员方法
其他类 中的方法引用
代码实现
- 其他类分装的成员方法 (上面引用该方法实现功能)
本类和父类方法的引用 - super - this
- 注意点,引用处不能是静态方法。
- this 本类方法引用
- super父类引用方法
3. 引用构造方法
- 这里有需
4 类名引用成员方法
5. 引用数组的构造方法
三、方法引用总结:
- 创建一个学生对象 Student 类,满足下面练习的需求
package com.fuctions.domain;
public class Student {
private String name;
private int age;
public Student() {
}
// 该方法用于方法引用
public Student (String str) {
String[] arr = str.split(",");
this.name = arr[0];
this.age = Integer.parseInt(arr[1]);
}
public Student(String name, int age) {
this.name = name;
this.age = age;
}
/**
* 获取
* @return name
*/
public String getName() {
return name;
}
/**
* 设置
* @param name
*/
public void setName(String name) {
this.name = name;
}
/**
* 获取
* @return age
*/
public int getAge() {
return age;
}
/**
* 设置
* @param age
*/
public void setAge(int age) {
this.age = age;
}
public String toString() {
return "Student{name = " + name + ", age = " + age + "}";
}
}
方法引用 - 练习一、
/**
* 方法引用练习一
*/
public static void main(String[] MakeFullStack) {
// 1. 创建一个集合并生成一些数据
ArrayList<String> list = new ArrayList<>();
Collections.addAll(list, "张三,23", "李四,24", "王五,25");
// 2. 将集合数据收集到Student类型的数组中
// 1. 使用方法Lambda + 方法引用实现
Student[] newArr = list.stream().map(Student::new).toArray(Student[]::new);
System.out.println(Arrays.toString(newArr)); // [Student{name = 张三, age = 23}, Student{name = 李四, age = 24}, Student{name = 王五, age = 25}]
// 2. 使用匿名内部类 + 方法引用实现
Student[] array = list.stream().map(new Function<String, Student>() {
@Override
public Student apply(String s) {
String keyName = s.split(",")[0];
int valueAge = Integer.parseInt(s.split(",")[1]);
return new Student(keyName, valueAge);
}
}).toArray(Student[]::new);
System.out.println(Arrays.toString(array)); // [Student{name = 张三, age = 23}, Student{name = 李四, age = 24}, Student{name = 王五, age = 25}]
}
方法引用 - 练习二、
/**
* 演示 方法引用练习二、
*/
// 1. 创建集合
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张三", 23));
list.add(new Student("李四", 24));
list.add(new Student("王五", 25));
//2. 需求; 获取对象的姓名,并存放到数组中
String[] nameArr = list.stream().map(Student::getName).toArray(String[]::new);
System.out.println(Arrays.toString(nameArr)); // [张三, 李四, 王五]
方法引用练习三、
- 代码示例:
我们现在 Student 类中进行添加 测试类中需要 引用到的方法
// 第一种方法
public String handleString () {
return String.format("%s-%d", this.name, this.age);
}
// 第二种方法
public static String handleString (Student student) {
String name = student.getName();
int age = student.getAge();
return String.format("%s-%d", name, age);
}
/**
* 演示 方法引用练习三、
*/
// 1. 创建集合
ArrayList<Student> list = new ArrayList<>();
list.add(new Student("张三", 23));
list.add(new Student("李四", 24));
list.add(new Student("王五", 25));
// 2. 将对象 使用 - 拼接字符串,放到数组数组中
// 第一种方法,方法引用
String[] StringArr = list.stream().map(Student::handleString).toArray(String[]::new);
System.out.println(Arrays.toString(StringArr)); // [张三-23, 李四-24, 王五-25]
// 第二种方法,指定流的类型,就不能使用方法引用,只能用 Lambda
// 使用显式类型转换来指定流中元素的类型
String[] stringArr2 = list.stream()
.map((Student student) -> Student.handleString(student))
System.out.println(Arrays.toString(StringArr2)); // [张三-23, 李四-24, 王五-25]
}