Lambda表达式可以看作是一段可以传递的代码,
Lambda表达式只能用于函数式接口,而函数式接口只有一个抽象方法,所以可以省略方法名,参数类型等
Lambda格式:(形参列表) -> Lambda体 ; 在java中Lambda表达式本质是函数式接口的实现
Runnable runnable = () -> System.out.println("执行任务") ;
Lambda语法:
java常见的函数式接口,可以根据自己的业务需求重新这些方法简化代码
Consumer,消费型接口,有参数无返回,对参数进行某种操作
void accept(T t);
Supplier,供给型接口,无参有返回,返回某个对象
T get();
Function,函数型接口,有参有返回,对 T类型的参数进行操作返回 R类型的结果
R apply(T t);
private static void extracted() {
// Function T为入参,R为返回结果
Function<Integer,String> function = (in)->{return in+"123";};
String apply = function.apply(12);
System.out.println(apply); //12123
}
Predicate,断定型接口,有参有返回,输入参数T,返回boolean值,用于判断对象是否满足某个条件
boolean test(T t);
其他函数式接口
当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用
方法引用是对Lambda的进一步简化,本质上就是Lambda表达式,而 Lambda 是函数式接口的实例,所以方法引用也是函数式接口的实例
语法为: 类(对象): : 方法名
方法引用 不需要方法的参数,调用可分为三种情况
情况2,类 : : 非静态方法 (在面向对象oop中是不允许的)
如下三种写法,从直接new到方法引用,代码的逻辑是完全一致的
private static void extracted1() {
Consumer<String> consumer =new Consumer<String>() {
@Override
public void accept(String s) {
System.out.println(s);
}
};
consumer.accept("写法1");
}
private static void extracted2() {
Consumer<String> consumer= (s)->System.out.println(s);
consumer.accept("写法2");
}
private static void extracted3() {
//方法引用是对Lambda的进一步简化,用来替换Lambda表达式,因为System.out对象的println方法已经实现过了,所以只需要直接调用就好了,不需要重新实现
//接口中的抽象方法的形参列表和返回值类型与方法引用的方法的形参列表和返回值类型完全相同,如下参数都是一个字符串,返回值都是void,所以可以使用参数引用
Consumer<String> consumer= System.out::println;
consumer.accept("写法3");
}
类似与方法应用,参数列表和返回值匹配就可以使用构造器引用,因为构造器也是方法
类名::new
同理,数组引用,可以把数组看作一个类
private static void extracted5() {
//下面两种写法都是创建一个 10个长的数组
Function<Integer,String[]> function = in-> new String[in];
String[] apply = function.apply(10);
Function<Integer,String[]> function1 = String[]::new;
String[] apply1 = function1.apply(10);
}
Java8 Stream
一个流式处理可以分为三个部分:
过滤:
filter,根据条件过滤
limit,操作也类似于SQL语句中的LIMIT关键字,不过相对功能较弱,limit返回包含前n个元素的流,当集合大小小于n时,则返回实际长度,
skip,操作与limit操作相反,如同其字面意思一样,是跳过前n个元素
distinct,操作类似于我们在写SQL语句时,添加的DISTINCT关键字,用于去重处理
public class StreamEntity {
private String name;
private Integer age;
private String high;
}
public static void test() {
//向集合中初始化了一些 StreamEntity 对象,以供操作
List<StreamEntity> list = getList();
//过滤 年龄大于25的对象 ,后续使用lambda打印
list.stream().filter(a -> a.getAge() > 25).forEach(a -> System.out.println(a));
//截取 集合中前两条数据 ,后续使用方法引用打印
list.stream().limit(2).forEach(System.out::println);
//跳过前两条数据
list.stream().skip(2).forEach(System.out::println);
//筛选,通过对象的hashcode和equals对集合中的数据进行去重
list.stream().distinct().forEach(System.out::println);
}
映射,包含两类映射操作:map和flatMap,就像sql可以仅输出我们需要的字段数据一样
//将元素中转换为其他形式或者提取信息 ,如下:提取对象中的年龄,并加1
list.stream().map(a->a.getAge()+1).forEach(System.out::println);
//flatMap
List<List<StreamEntity>> res =new ArrayList<>();
res.add(list);
res.add(list);
//这里已经把集合中的集合全部拆出来了
Stream<String> objectStream = res.stream().flatMap(a -> a.stream().map(b->b.getName()));
objectStream.forEach(System.out::println);
排序
sorted(),进行自然排序,如果排序的对象没有实现 Comparator ,也就是没有排序规则,会报错
sorted(Comparator super T> comparator),如果排序的对象没有实现 Comparator ,也可以传入一个比较器
//按照年龄自然排序
list.stream().map(a->a.getAge()).sorted().forEach(System.out::println);
//传入比较器
list.stream().sorted((a, b) -> a.getAge() - b.getAge()).forEach(System.out::println);
//使用方法引用为:
list.stream().sorted(Comparator.comparingInt(StreamEntity::getAge)).forEach(System.out::println);
不调用终止操作,中间操作是不会执行的,调用终止操作产生结果后,stream就不能再被使用了
查找
//
boolean b = list.stream().map(a -> a.getAge()).allMatch(a -> a > 30);
// 用于返回满足条件的第一个元素,查找条件可以通过filter设置
Optional<Integer> first = list.stream().map(a -> a.getAge()).filter(a -> a > 30).findFirst();
Integer integer = first.get()
long count = list.stream().count();
//根据自定义比较器求最大
StreamEntity s1 = list.stream().max((a, b) -> a.getAge() - b.getAge()).get();
//根据自定义比较器求最小
StreamEntity s2 = list.stream().min((a, b) -> a.getAge() - b.getAge()).get();
//迭代
list.stream().forEach(a-> System.out.println(a.getAge()+1));
归约
// 获取年龄的总和
Integer s1 = list.stream().map(a -> a.getAge()).reduce((b, d) -> b + d).get();
// reduce 的一个参数是初始值
Integer s2 = list.stream().map(a -> a.getAge()).reduce(0, (b, d) -> b + d);
收集
//转换为 list
List<StreamEntity> collect = list.stream().collect(Collectors.toList());
//转化为 map
Map<Integer, StreamEntity> collect1 = list.stream().collect(Collectors.toMap(a -> a.getAge(), a -> a));
//转换为 set
Set<String> collect2 = list.stream().map(a -> a.getName()).collect(Collectors.toSet());
分组,在数据库操作中,我们可以通过GROUP BY关键字对查询到的数据进行分组,java8的流式处理也为我们提供了这样的功能,Collectors.groupingBy来操作集合
常见方法:
创建Optional 对象
empty() 创建空的实例
of(T t),t不能为空
ofNullable(T t)
获取Optional 对象的值