如果一个接口中,只声明了一个抽象方法,则此接口就称为函数式接口
可以通过Lambda表达式来创建该接口的对象。(若Lambda表达式抛出一个受检异常,那么该异常需要在目标接口的抽象方法上进行声明)
可以在一个接口上使用@FunctionalInterface
注解,来检查他是否式一个函数式接口。
在java.util.function包下定义了java8的丰富的函数式接口。
自定义函数式接口:
/**
* @Author: mei_ming
* @DateTime: 2022/6/3 9:43
* @Description: FunctionalInterface : 检验FuncInterface 是否为函数式接口
*/
@FunctionalInterface
public interface FuncInterface {
void test();
// void test1();
}
在Java8中Lambda表达式就是一个函数式接口的实例
函数式接口 | 参数类型 | 返回类型 | 用途 |
---|---|---|---|
Consumer < T > 消费型接口 | T | void | 对类型为T的对象应用操作,包含方法 void accept(T t) |
Supplier < T > 供给型接口 | 无 | T | 返回类型为T的对象,包含方法 T get() |
Function < T > 函数型接口 | T | R | 对类型为T的对象应用操作,并返回结果是R类型的对象,包含方法 R apply(T t) |
Predicate < T > 断定型接口 | T | boolean | 对类型为T的对象应用操作,并返回boolean值,包含方法 boolean test(T t) |
import org.junit.Test;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
import java.util.function.Predicate;
/**
* @Author: mei_ming
* @DateTime: 2022/6/3 9:45
* @Description: TODO
*/
public class LambdaDemo2 {
@Test
public void test1(){
happyTime(500, new Consumer<Double>() {
@Override
public void accept(Double aDouble) {
System.out.println("学习消费价格:"+aDouble);
}
});
System.out.println("-------------");
happyTime(300, money-> System.out.println("娱乐消费价格:"+money));
}
public void happyTime(double money, Consumer<Double> con){
con.accept(money);
}
@Test
public void test2(){
List<String> list = Arrays.asList("东京","北京","南京","西京","天津");
List<String> strings = filterString(list, new Predicate<String>() {
@Override
public boolean test(String s) {
return s.contains("京");
}
});
System.out.println(strings);
System.out.println("-------------");
List<String> strings2 = filterString(list, s-> s.contains("京"));
System.out.println(strings2);
}
public List<String> filterString(List<String> list, Predicate<String> pre){
ArrayList<String> filterStr= new ArrayList<>();
for (String s:list) {
if(pre.test(s)){
filterStr.add(s);
}
}
return filterStr;
}
}
什么是方法引用:
当要传递给Lambda体的操作,应有实现的方法了,可以使用方法引用!
方法引用就是Lambda表达式,也就是函数式接口的一个实例,通过方法的名字来指向一个方法,可以认为是Lambda表达式的一个语法糖。
要求:
实现接口的抽象方法的参数泪飙和返回值类型,必须与方法引用的方法参数列表和返回值类型保持一致!
格式:
使用操作符 “::” 将类(或对象)与方法名分隔开来。
主要使用情况:
import org.junit.Test;
import java.io.PrintStream;
import java.util.Comparator;
import java.util.function.Consumer;
import java.util.function.Function;
/**
* @Author: mei_ming
* @DateTime: 2022/6/3 10:14
* @Description: 方法引用
*/
/**
* 使用情景: 当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用!
*
* 方法引用,本质上就是Lambda表达式,而lambda表达式作为函数式接口的实例。所以方法引用,也是函数式接口的实例
*
* 使用格式:类(或对象) :: 方法名
*
* 情况1 对象 :: 非静态方法
* 情况2 类 :: 静态方法
* 情况3 类 :: 非静态方法
*
* 方法引用的使用要求:要求接口中的抽象方法的形参列表和返回值类型与方法应用的方法的形参列表和返回值类型相同!(针对情况1和2)
*
*/
public class LambdaDemo3 {
// 一、对象 :: 非静态方法
// Consumer中的 void accept(T t)
// PrintStream中的void println(T t)
@Test
public void test1(){
Consumer<String> con1 =str-> System.out.println(str);
con1.accept("北京");
System.out.println("-------------");
PrintStream ps = System.out;
Consumer<String> con2 = ps :: println;
con2.accept("beijing");
}
//二、类::静态方法
//Comparator中的int compare(T t1,T t2)
//Integer中的int compare(T t1,T t2)
@Test
public void test2(){
Comparator<Integer> com1=(t1,t2)->Integer.compare(t1,t2);
System.out.println(com1.compare(12,21));
System.out.println("-------------");
Comparator<Integer> com2= Integer::compare;
System.out.println(com2.compare(12,6));
}
//Function中的R apply(T t)
//Math中的Long round(Double d)
@Test
public void test3(){
Function<Double,Long> fun1=d -> Math.round(d);
System.out.println(fun1.apply(12.3));
System.out.println("-------------");
Function<Double,Long> fun2 = Math::round;
System.out.println(fun2.apply(12.6));
}
//三、类::非静态方法
//Comparator中的int compare(T t1,T t2)
//String中的int t1.compare(t2)
@Test
public void test4(){
Comparator<String> com1=(t1,t2)->t1.compareTo(t2);
System.out.println(com1.compare("abc","abd"));
System.out.println("-------------");
Comparator<String> com2= String::compareTo;
// 这个String 是 上面t1类型的返回值
System.out.println(com2.compare("abc","abe"));
}
}
import org.junit.Test;
import java.util.Arrays;
import java.util.function.BiFunction;
import java.util.function.Function;
import java.util.function.Supplier;
/**
*
* 1. 构造器引用
* 和方法引用类似,函数式接口的抽象方法的形参列表和构造器中的形参列表一致
* 抽象方法的返回值级构造器所属的类的类型
*
* 2. 数组引用
* 看成一个特殊的类
*/
public class LambdaDemo4 {
//一、构造器引用
//Supplier中的T get()
//Cat的 Cat()
@Test
public void test1(){
//原始
Supplier<Cat> sup = new Supplier<Cat>() {
@Override
public Cat get() {
return new Cat();
}
};
sup.get();
System.out.println("---------");
//lambda
Supplier<Cat> sup1 = ()-> new Cat();
sup1.get();
System.out.println("---------");
//构造器引用
Supplier<Cat> sup2 = Cat::new;
sup2.get();
}
//Function中R apply(T t)
//Cat的 Cat(String name)
@Test
public void test2(){
//lambda
Function<String,Cat> fun1 = (name)-> new Cat(name);
Cat cat = fun1.apply("小花");
System.out.println(cat);
System.out.println("---------");
//构造器引用
Function<String,Cat> fun2 =Cat::new;
Cat cat1 = fun2.apply("小草");
System.out.println(cat1);
}
//BiFunction中R apply(T t,U u)
//Cat的 Cat(String name)
@Test
public void test3(){
//lambda
BiFunction<String,Integer,Cat> fun1 = (name,age)-> new Cat(name,age);
Cat cat = fun1.apply("小花",1);
System.out.println(cat);
System.out.println("---------");
//构造器引用
BiFunction<String,Integer,Cat> fun2 =Cat::new;
Cat cat1 = fun2.apply("小草",2);
System.out.println(cat1);
}
//二、数组引用
//Function中的R apply(T t)
@Test
public void test4(){
//lambda
Function<Integer,String[]> fun1=length->new String[length];
String[] str1 = fun1.apply(5);
System.out.println(Arrays.toString(str1));
System.out.println("---------");
//数组引用
Function<Integer,String[]> fun2=String[]::new;
String[] str2 = fun2.apply(10);
System.out.println(Arrays.toString(str2));
}
}