Lambda表达式
- 概念:
本质上是一个对象,可以当作是匿名内部类创建的对象的简写格式。 - 格式:
(参数)->{方法体} - 说明:
参数:需要重写的抽象方法中的形参列表
->:为了分隔前后两部分,Lambda运算符或者箭头运算符
方法体:需要对抽象方法重写的内容 - 举例:
(1)如果抽象方法没有参数,方法体只有一句:
方法体外的大括号可以省略。
格式:()->方法体语句;
(2)如果抽象方法中有一个参数:
参数的类型可以省略,参数外的小括号可以省略
格式:参数名->{方法体语句};
(3)如果方法的参数有多个:
参数外的小括号不能省略,参数类型可以省略,方法体外的大括号可以省略。
格式:(参数名称)->方法体语句;
(4)如果方法有返回值:
直接在方法体中的大括号中对数据进行return即可
格式:(参数名称)->{
方法体语句:
return语句;
};
(5)如果方法需要返回值,而且方法体只有一句:
可以将大括号和return关键字一起省略
格式:(参数名称)->要返回的数据; - Lanbda表达式和匿名内部类的区别:
(1)如果接口中只有一个抽象方法,既可以使用匿名内部类创建,也可以使用Lambda创建。
如果接口中有多个抽象方法,那么只能使用匿名内部类创建
(2)在传递实际参数时,如果形参是接口,可以使用Lambda表达式传递,也可以使用匿名内部类传递。
如果形参是某一类型,只能使用匿名内部类传递。(原因:不能使用Lambda表达式创建抽象类的子类对象)
(3)匿名内部类会在磁盘中生成一个字节码文件,Lambda表达式则没有
函数式接口
- 概念:
一个接口中如果只有一个抽象方法,那么这个接口就是一个函数式接口。 - 通过注解检测一个接口是否是一个函数式接口:
@FunctionalInterface
在接口上直接加上注解,如果这个接口是一个函数式接口则不报错,否则编译报错 - 使用场景:
(1)Lambda表达式的使用前提
(2)可以将函数式接口定义为方法的形参,再调用方法时,可以将利用Lambda表达式当作实参进行传递。
(3)可以将函数式接口定义为方法的返回值类型,在调用方法时,可以利用Lambda表达式返回数据。
内置的函数式接口
1、在jdk8之后,官方定义了一些常用的函数式接口,如果以后需要使用类似的接口,直接使用即可,不需要再单独定义。
2、分类:
-Consumer :消费型接口
void accept(T t)
-Supplier :供给型接口
T get()
-Function<T,R> :函数型接口
R apply(T t)
-Predicate :断言型接口
boolean test(T t);
消费型接口
- Consumer
void accept(T t):消费一个参数数据
default Consumer andThen(Consumer<? super T> after) :
返回一个组合的 Consumer ,按顺序执行该操作,然后执行 after操作。 - 概述:该接口中的方法可以接收一个参数,接收的参数类型由泛型指定,对参数的操作方式根据该接口的实现类决定,不需要返回值。
public static void main(String[] args) {
Consumer<String> c1 = s->System.out.println(s);
Consumer<String> c2 = s->System.out.println(s.length());
//执行两个用andThen()
get("雀食蟀",c1.andThen(c2));
}
public static void get(String s,Consumer<String> con) {
con.accept(s);
}
供给型接口
- Supplier :
T get():该方法不需要参数,它会按照某种逻辑,返回一个具体的数据 - 概述:
该接口也被称为生产型接口,如果指定了泛型是什么类型,那类中的get方法就会返回一个该类型的一个具体数据。返回的数据,由该接口的实现类对象决定。
// 1、定义一个方法,该方法可以返回一个集合,集合中可以存储10个1-10的随机整数。
public static void main(String[] args) {
System.out.println(get(()->new Random().nextInt(10)+1));
}
public static ArrayList<Integer> get(Supplier<Integer> s){
ArrayList<Integer> list = new ArrayList<Integer>();
for(int i = 1; i<=10;i++) {
int x = s.get();
list.add(x);
}
return list;
}
函数型接口
- Function<T,R>
R apply(T):接收一个数据,操作数据之后,返回一个新的数据
default Function andThen(Function f):
先通过调用者对象处理参数,将处理的结果再通过f对象处理,将两个处理的结果进行返回。 - 概述:
该接口可以接收一个数据,数据的类型根据泛型指定,然后通过该接口的实现类对象对该数据进行操作,操作之后返回一个新的数据。
public static void main(String[] args) {
System.out.println(get("100",s->Integer.parseInt(s)));
}
//输入字符串类型,返回整数类型
public static Integer get(String s,Function<String, Integer> f) {
Integer i = f.apply(s);
return i;
}
断言型接口
- Predicate:
boolean test(T t):对数据做出指定的判断 - 概述:
该接口是一个判断接口,接口可以接收一个指定泛型的参数,并根据该接口的实现类 对象对该参数做出对应的判断,返回只为boolean类型 - 额外功能:
and(Predicate p):先将参数通过调用者判断真假,再将参数通过p判断真假,全真为真,否则为假
or(Predicate p):全假为假,否则为真
negate():取反
public static void main(String[] args) {
Predicate<Integer> p1 = i-> i>=100;
Predicate<Integer> p2 = i-> i<=100;
System.out.println(p1.and(p2).test(100));//true
System.out.println(p1.or(p2).test(101));//true
//将参数使用p1的方式判断,将判断结果取反
System.out.println(p1.negate().test(100));//false
}
方法引用
1、概念:
对lambda表达式的扩展,在定义lambda表达式中的重写内容时,如果这个重写的内容之前已经写过,只需要去调用即可,不需要再写一遍。
2、格式:
如果是一个构造方法:类名::new
如果是一个静态方法:类名::方法名
如果是一个非静态方法:对象名::方法名
Stream类
- 概述:Java8之后提供的一个新的类型,该类型可以更加方便的操作一系列元素。
Stream类对象的获取
- Collection集合的获取方式:
对象名.stream(); - Map集合获取方式:
ketSet().Stream();
values().stream();
entrySet.stream(); - 数组的获取方式:
Strem.of(数组名);
Stream类的常用方法
- Stream类中包含了一些对数据过滤和筛选以及获取的方法。
- 分类:
延迟方法:使用完这个方法之后,返回值也是一个Stream类的对象,可以继续调用类中的方法。
终结方法:使用完这个方法之后,返回值不再是一个Stream类的对象,不能继续使用这个类中的方法。
3、方法罗列:
(1)forEach(Consumer<? super T> action) :终结方法
该方法可以自动获取流中每一个数据,并对获取的数据操作
数据的操作方式根据消费型接口的实现类重写。
(2)count() :返回此流中的元素数。终结方法
(3)filter(Predicate<? super T> predicate) :延迟方法
该方法可以自动获取流中的每一个数据进行判断,如果数据判断结果为真,就在流中存储,否则不存储该数据
(4)limit(long m) :将流中的前m个元素保留,其余的删除 延迟方法
(5)skip(long n) : 跳过前n个元素,保留后面的元素 延迟方法
(6)map(Function<? super T,? extends R> mapper) : 延迟方法
该方法自动获取流中的每一个数据,并对数据处理,处理之后返回一个新的数据。具体的处理方式根据实现类对象确定。
(7)concat(Stream<? extends T> a, Stream<? extends T> b): 延迟方法(静态方法)
将两个流中的数据进行合并,合并为一个流对象
(8)distinct():去除流中重复的元素 延迟方法
(9)toArray():把stream流中的数据收集到数组中
(10)collect(Collector c):把stream流中的数据收集到指定的集合中
Collector:参数的类型 是一个接口获取可以通过工具类Collectors的方法获取
常用:
获取List集合:Collectors.toList()
获取Set集合: Collectors.toSet()