Stream流和lambda表达式的学习
lambda表达式和匿名内部类的区别:
1、所需类型不同:
- 匿名内部类:可以是接口,可以是抽象类,也可以是具体类
- lambda表达式:只能是接口
2、使用限制不同:
- 如果接口中有且仅有一个抽象方法,可以使用lambda表达式,也可以使用匿名内部类
- 如果接口中又多个抽象方法,只能使用匿名内部类,不能使用lambda表达式
3、实现原理不同:
- 匿名内部类:编译之后,产生一个单独的.class字节码文件
- lambda表达式:编译之后,没有单独的.class字节码文件。对应的字节码文件会在运行的时候动态生成。
lambda表达式和stream流
lambda
表达式:
- 1、只能操作接口,不能操作类
- 2、接口当中有且仅有一个抽象方法(没有或者有两个及以上都不行)
Stream
流的获取方法:
1 、单列集合:
- 可以使用
Collection
接口中的,默认方法stream()
2、双列集合:
间接
生成流对象- 可以先通过
KeySet()
或者entrySet()
获取到一个Set
集合,之后在使用stream()
流3、数组:
- 可以使用
Arrays
对象中的静态方法stream()
生成流对象4、同中数据类型的多组数据:
- 1,2,3,4…
- “a”,“b”,“c”,“d”…
- 使用
Stream.of(T...values)
生成流对象
单列集合
// 创建一个集合,并添加数据
private static List<String> list = new ArrayList<String>(List.of("张三","李四","王五","赵六","张三丰","令狐冲"));
// 遍历集合:使用lambda表达式
list.forEach(System.out::println);
// 遍历集合:使用stream流和lambda表达式
list.stream().forEach(System.out::println);
双列集合
private static Map<String, Object> map = new HashMap<>();
static{
map.put("张三", "23");
map.put("李四", "24");
}
public static void testMap(){
// 使用stream流和lambda表达式遍历所有key
map.keySet().stream().forEach(System.out::println);
// 使用stream流和lambda表达式遍历所有key-value
map.entrySet().stream().forEach(System.out::println);
}
KeySet()
和entrySet()
使用stream()
流的区别:
keySet
:先获取到所有的key
得到一个Set
集合,再把这个Set
集合中所有的key
放到steam()
中map.keySet().stream()
,之后在遍历数据entrySet
:先获取到所有的键值对(key-value)得到一个Set
集合对象Set<Map.Entry<String, Object>>
,在把这个Set
集合对象中所有的键值对放到stream()
流中map.entrySet().stream()
,之后在遍历数据
数组
数组使用
stream()
流时,可以直接使用Arrays
中的静态方法获取
public static void testArr() {
String[] str = {"aaa", "bbb", "ccc", "ddd"};
Arrays.stream(str).filter(s -> s.toUpperCase().startsWith("A")).forEach(System.out::println);
}
多组数据
直接调用
Stream
中的静态方法of()
即可直接获取使用
public static void testStr(){
Stream.of("张三",23,"李四",24,"王五",25).forEach(System.out::println);
}
Stream流中常见中间操作方法
filter()
:用于对流中的数据进行过滤
limit()
:截取
指定参数个数的数据,limit(3)
表示截取前三个(保留前面的,舍弃后面的)skip()
:跳过
指定参数个数的数据,skip(3)
表示前三个跳过不要了(舍弃前面的,保留后面的)concat()
:合并
将a、b两个流合并到一起,返回一个新的stream
流distinct()
:去重
去除流中的重复元素,依赖hashCode()
和equals()
方法
stream流中常见的终结操作方法
forEach()
:对流中的每个元素执行操作count()
:返回流中的元素个数
stream流的收集方法
工具类Collectors
提供了具体的收集方式
collect(Collector collector)
Collector toList()
:把元素手机到List
集合中Collector toSet()
:把元素收集到Set
集合中Collector toMap(Function KeyMapper,function valueMapper)
:把元素收集到Map
集合中
filter()
// 条件过滤:获取以"张"开头并且长度为3的数据
list.stream().filter(s -> s.startsWith("张")).filter(s -> s.length() == 3).forEach(s -> System.out.println(s));
// 条件过滤:简略版
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
limit()
截取指定数据
// 只要前3个数据,后面的丢弃
list.stream().limit(3).forEach(System.out::println);
skip()
跳过指定数据
// 去掉前3个数据,只要后面的
list.stream().skip(3).forEach(System.out::println);
concat()
合并stream流数据
// 合并stream流数据
Stream.concat(list.stream(), map.keySet().stream()).filter(s -> s.startsWith("张")).forEach(System.out::println);
Stream.concat(list.stream(), map.keySet().stream()).forEach(System.out::println);
distinct()
去除重复数据
list.stream().distinct().forEach(System.out::println);
stream流和lambda表达式的使用
public static void test() {
System.out.println("=========== 基本使用 =========");
list.stream().filter(new Predicate<String>() {
// 对给定的参数判断,返回Boolean值,为true则保留,为fasle则不保留
@Override
public boolean test(String s) {
boolean res = s.startsWith("张");
return res;
}
}).forEach(s -> System.out.println(s));
System.out.println("=========== 简化使用 =========");
list.stream().filter((String s) -> {
boolean res = s.startsWith("张");
return res;
}).forEach(s -> System.out.println(s));
System.out.println("=========== 简化使用 =========");
list.stream().filter(s -> s.startsWith("张")).forEach(s -> System.out.println(s));
System.out.println("=========== 简化使用 =========");
list.stream().filter(s -> s.startsWith("张")).forEach(System.out::println);
}
== 结论:在Stream
流中无法直接修改集合、数组等数据源中的数据,过滤、合并、截取等操作只是修改的是stream
流中的数据,源数据并未改变 ==
工具类Collectors
filter()
:负责过滤数据
collect()
:负责收集过滤后的数据(不会创建容器,也不负责把数据添加到容器中)
Collector.toList()
:底层会创建一个容器,并把数据添加到容器中
//toList
List<String> resList = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toList());
resList.forEach(System.out::println);
// toSet()
Set<String> set = list.stream().filter(s -> s.startsWith("张")).collect(Collectors.toSet());
set.forEach(System.out::println);
//toMap
Map<String, String> collectMap = Stream.of("张三, 23", "李四, 24", "王五, 25").collect(Collectors.toMap(
// s是一组一组的字符串("张三, 23")
s -> s.split(",")[0],
s -> s.split(",")[1]
));
collectMap.entrySet().forEach(System.out::println);