先来一段传统的匿名内部类调用程序
//定义一个数学接口
public interface Maths {
//定义一个计算的接口方法
int calc(int a, int b);
}
//测试类
public class MathsTester {
//定义一个打印计算结果的方法
public static void printCalcResult(int a,int b,Maths maths){
System.out.println(maths.calc(a, b));
}
}
//传统的匿名内部类使用方法
public static void main(String[] args) {
//定义两个数
int a = 10;
int b = 5;
//两个数相加;
MathsTester.printCalcResult(a, b, new Maths() {
@Override
public int calc(int a, int b) {
return a + b;
}
});
//两个数相减;
MathsTester.printCalcResult(a, b, new Maths() {
@Override
public int calc(int a, int b) {
return a * b;
}
});
}
使用Lambda表达式后
public static void main(String[] args) {
//定义两个数
int a = 10;
int b = 5;
//使用lambda表达式定义4个接口的实现类,(num1, num2):括号中的参数不能与外面的变量a和b重名
Maths add = (num1, num2) -> num1 + num2; //加
Maths sub = (num1, num2) -> num1 + num2; //减
//打印计算结果
MathsTester.printCalcResult(a, b, add);
MathsTester.printCalcResult(a, b, sub);
//简单的写法
MathsTester.printCalcResult(a, b, (num1, num2) -> num1 * num2);
MathsTester.printCalcResult(a, b, (num1, num2) -> num1 / num2);
//先判断,在选择如何计算,有多行语句时,要使用花括号{}
MathsTester.printCalcResult(a, b, (num1, num2) -> {
if (num1 > num2) {
return num1 - num2;
} else {
return num1 + num2;
}
});
//直接调用接口方法
System.out.println(add.calc(a, b));
System.out.println(add.calc(a, b));
//无参数lambda表达式:() -> xxx
//仅当接口的方法有且仅有一个抽象方法时,才能使用lambda表达式
}
函数式接口
函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。函数式接口可以被隐式转换为 lambda 表达式
//使用注解定义该接口是一个函数式接口,也可以不加注解,只要遵循函数式接口的定义就可以 了,使用注解java编译器会自动识别错误
@FunctionalInterface
public interface Hello {
//抽象方法有且只有一个
void hello();
//默认方法,jdk8以前是不允许在接口中的方法有方法体的,可以定义多个默认方法
default void hi(){
System.out.println("hi..........");
}
default void o(){
System.out.println("o...........");
}
//可以定义静态方法
static void he(){
System.out.println("he..........");
}
}
//接口实现类
public class HelloImpl implements Hello {
//接口抽象方法实现
@Override
public void hello() {
// TODO Auto-generated method stub
}
//可以重写父接口的默认方法,也可以不重写,Hello.o()方法,我们就没重写
@Override
public void hi() {
Hello.super.hi(); //调用父接口的实现
System.out.println("..........hi");
}
public static void main(String[] args) {
//常规接口实例化
Hello hello = new HelloImpl();
hello.hi();
//lambda表达式实例化接口
Hello _hello = () -> System.out.println("ho......");
_hello.hello();
_hello.o();
//调用父接口的静态方法
Hello.he();
}
}
内置的函数式接口
java.util.function 包下含了很多函数式接口,这里我们主要讲解四个核心接口,其他接口依葫画瓢
@FunctionalInterface
public interface Consumer {
void accept(T t); //表示接受单个输入参数并且不返回结果的操作
......
}
@FunctionalInterface
public interface Supplier {
T get(); //获得结果
}
@FunctionalInterface
public interface Function {
R apply(T t); //输入一个参数,返回一个结果R
......
}
@FunctionalInterface
public interface Predicate {
boolean test(T t); //输入一个参数,返回布尔值
......
}
public class Tester {
//Consumer
public void happy(double money, Consumer consumer){
consumer.accept(money);
}
@Test
public void testHappy(){
happy(1000, (m) -> System.out.println("这次去happy,一共消费了"+m+"元"));
}
//Supplier
public List fillList(int size,Supplier supplier){
List list = new ArrayList();
for (int i = 0; i < size; i++) {
list.add(supplier.get());
}
return list;
}
@Test
public void testFillList(){
System.out.println(fillList(10, () -> Math.random() + ""));
}
//Function
public String strHandler(String str, Function fun){
return fun.apply(str);
}
@Test
public void testStrHandler(){
System.out.println(strHandler("\t\t\t清除两端空格 ", (str) -> str.trim()));
}
//Predicate
public List filterStr(List list, Predicate pre){
List newList = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
if(pre.test(list.get(i))){
newList.add(list.get(i));
}
}
return newList;
}
@Test
public void testFilterStr(){
List list = new ArrayList<>(Arrays.asList("Hello", "atguigu", "Lambda", "www", "ok"));
System.out.println(filterStr(list, (s) -> s.length() > 3));
}
}
其他函数式接口描述:https://www.runoob.com/java/java8-functional-interfaces.html
方法引用
方法引用比lambda表达式代码量更简洁
public static void main(String[] args) {
//lambda表达式的写法
Consumer consumer = (str) -> System.out.println(str);
//方法引用的写法,使用两个英文冒号,后面跟方法名
//要求println方法的入参和返回值和Consumer接口的方法一直才能这样使用
Consumer _consumer = System.out::println;
//其他示例
Supplier supplier = () -> Math.random();
Supplier _supplier = Math::random; //使用静态方法
//使用第一个参数的方法进行调用
BiPredicate bp = (x, y) -> x.equals(y);
BiPredicate bp2 = String::equals;
System.out.println(bp.test("abcde", "abcde"));
//比较两个Employee类
BiPredicate biPredicate = (e1,e2) -> e1.compare(e2);
//第一个入参是e1,返回值时使用e1.compare返回的,这种情况就可以简写为e1::xxx
BiPredicate bp3 = Employee::compare;
System.out.println(bp3.test(new Employee("zhangsan"), new Employee("lisi")));
//构造方法引用
Supplier supplier3 = Employee::new;
Employee employee = supplier3.get();
//有参构造方法引用
Function function = Employee::new;
Employee employee2 = function.apply("wangwu");
//数组引用
Function fun = (size) -> new String[size];
Function fun2 = Employee[] :: new;
}
public class Employee {
private int id;
private String name;
private int age;
private double salary;
public Employee() { }
public Employee(String name) {
this.name = name;
}
public boolean compare(Employee employee){
return this.getName().equals(employee.getName());
}
}