Lamdba表达式
方法引用
先来看一下什么是方法引用:
方法引用其实是Lambda表达式的另一种写法,当要传递给Lambda体的操作,已经有实现的方法了,可以使用方法引用;
注意: 实现抽象方法的参数列表,必须与方法引用方法的参数列表保持一致!
方法引用:使用操作符::将方法名和对象或类的名字分隔开来,三种主要使用情况为:
- 对象::实例方法
- 类::静态方法
- 类::实例方法
对象::实例方法
import java.util.function.Consumer; public class MyTest { public static void main(String[] args) { Consumer<String> consumer = new Consumer<String>() { @Override public void accept(String s) { System.out.println(s); }
}; consumer.accept("aaaaaaaaaaaaaa"); //aaaaaaaaaaaaaa //简写1: Consumer<String> consumer1 = (String s) -> { System.out.println(s); }; consumer1.accept("abc"); //abc //简写2: Consumer<String> consumer2 = (s) -> System.out.println(s); consumer2.accept("bcd"); //bcd //简写3: Consumer<String> consumer3 = System.out::println; consumer3.accept("abc"); //abc } }
为什么可以写成上述方式?
因为:System.out.println(s);与void accept(String s)一样,都是使用s作为参数,返回值是void,因此就可以简写为简写3;
类::静态方法
import java.util.function.BinaryOperator; public class MyTest1 { public static void main(String[] args) { BinaryOperator<Double> operator = new BinaryOperator<Double>(){ @Override public Double apply(Double o, Double o2) { return Math.max(o,o2); } }; System.out.println(operator.apply(2.13, 3.12));//3.12 BinaryOperator<Double> operator2 = (o, o2) -> Math.max(o,o2); System.out.println(operator2.apply(2.13, 3.12));//3.12 BinaryOperator<Double> operator3 = Math::max; Double max = operator3.apply(5.0, 20.0); System.out.println(max);//20.0 } } 因为Math.max()所需要的参数以及返回值与重写的accpet()一样,因此可以简写为类::静态方法; import java.util.Comparator; public class MyTest2 { public static void main(String[] args) { Comparator<Integer> comparator = new Comparator<Integer>() { @Override public int compare(Integer o1, Integer o2) { return Integer.compare(o1,o2); } }; System.out.println(comparator.compare(20, 12));//1 Comparator<Integer> comparator1 = Integer::compareTo; System.out.println(comparator1.compare(20, 12));//1 } }
类::实例方法
import java.util.Comparator; public class MyTest2 { public static void main(String[] args) { Comparator<String> comparator = new Comparator<String>() { @Override public int compare(String o1, String o2) { return o1.compareTo(o2); } }; System.out.println(comparator.compare("20", "12"));//1 Comparator<String> comparator1 = String::compareTo; System.out.println(comparator1.compare("20", "12"));//1 } }
为什么可以这样写?、
传递过来的两个参数,一个作为调用者,一个作为参数,这时候,使用类::实例方法简写;
构造引用
格式:ClassName::new
与函数式接口相结合,自动与函数式接口中方法兼容。可以把构造器引用赋值给定义的方法,构造器参数列表要与接口中抽象方法的参数列表一致!
import java.util.function.Supplier; public class Mytest3 { public static void main(String[] args) { Supplier<Student> supplier = new Supplier<Student>() { @Override public Student get() { return new Student(); } }; Student student = supplier.get(); Supplier<Student> supplier1 = () -> new Student(); Student student1 = supplier1.get(); } } public class Mytest3 { public static void main(String[] args) { Supplier<Student> supplier = new Supplier<Student>() { @Override public Student get() { return new Student("张三",23); } }; Student student = supplier.get(); System.out.println(student); Supplier<Student> supplier1 = () -> new Student("李四",25); Student student1 = supplier1.get(); System.out.println(student1); } } public class MyTest4 { public static void main(String[] args) { Student student = new Student("张三", 23); BiFunction<String, Integer, Student> function = new BiFunction<String, Integer, Student>() { @Override public Student apply(String s, Integer integer) { return student; } }; BiFunction<String, Integer, Student> function1 = (s, integer) -> student; BiFunction<String, Integer, Student> function2 = Student::new; } }
之所以可以这样简写,是因为构造方法的形参和返回值与重写的方法一样;
四大常用的函数式接口
消费型接口
基本格式:
Consumer<T> 接受一个输入参数并且无返回值。
方法调用:void accept(T t);
@Test public void testConsumer() { handle(6, (x) -> System.out.println(x + 2)); } public void handle(int value, Consumer<Integer> consumer) { consumer.accept(value); }
因为没有返回值,所以常用于打印、发送短信等消费动作。
供给型接口
基本格式:
Supplier<T> 无输入参数,返回一个结果T。
方法调用:T get();
@Test public void testSupplier() { Person person = Person.builder() .name("供给者") .build(); System.out.println(getObject(() -> person.getName())); } public String getObject(Supplier<String> supplier) { return supplier.get(); }
常用于符合条件时调用获取结果;运行结果提前定义,但不运行。
函数型接口
基本格式:
Function<T,R> 接受一个输入参数T,返回一个结果R。
方法调用:R apply(T t);
@Test public void testFunction() { int result = plusTwo(6, (x) -> x + 2); System.out.println(result); int before = before(6, x -> x + 2, x -> x * 10); // 62 System.out.println(before); int after = after(6, x -> x + 2, x -> x * 10); // 80 System.out.println(after); } public Integer plusTwo(int origen, Function<Integer, Integer> function) { return function.apply(origen); } public Integer before(int value, Function<Integer, Integer> function1, Function<Integer, Integer> function2) { // value作为function2的参数,返回一个结果,该结果作为function1的参数,返回一个最终结果 return function1.compose(function2).apply(value); } public Integer after(int value, Function<Integer, Integer> function1, Function<Integer, Integer> function2) { // value作为function1的参数,返回一个结果,该结果作为function2的参数,返回一个最终结果 return function1.andThen(function2).apply(value); }
断言型接口
基本格式:
Predicate<T> 接受一个输入参数T,返回一个布尔值结果。
方法调用:boolean test(T t);
@Test public void testPredicate() { boolean judge = judge(6, (x) -> (x & 1) != 1); System.out.println(judge); List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9); System.out.println("输出所有数据:"); eval(list, x -> true); // 1 2 3 4 5 6 7 8 9 System.out.println(); System.out.println("输出所有偶数:"); eval(list, x -> (x & 1) != 1); // 2 4 6 8 System.out.println(); System.out.println("输出大于 3 的所有数字:"); eval(list, x -> x > 3); // 4 5 6 7 8 9 System.out.println(); // 验证输入是否正确 boolean valid = valid("许宣", x -> !x.isEmpty() && x.length() <= 3); System.out.println(valid); } public boolean judge(Integer input, Predicate<Integer> predicate) { return predicate.test(input); } public static void eval(List<Integer> list, Predicate<Integer> predicate) { for (Integer n : list) { if (predicate.test(n)) { System.out.print(n + " "); } } } public boolean valid(String name, Predicate<String> predicate) { return predicate.test(name); }
常用于条件判断