Java学习笔记_Lambda学习
在Java8之前,如果想“让参数具备行为能力”,即将代码块作为参数进行传递,这是很不方便的。比较普遍的方式就是创建一个类的实例对象,让实例去调用这个方法,从而达到代码块的传递。
1.函数式接口
概念:有且仅有一个抽象方法(但可以有其他方法,如:静态方法和默认方法【默认方法主要是为了拓展其实现类时可以不重写接口中的某些方法,提高可拓展性】)的接口,因为只有一个抽象方法才能确保Lambda进行顺利的推导
注解:@FunctionalInterface
// JDK内置的函数式接口 JDK1.8提供的内置函数式接口可以在java.util.function包下获
@FunctionalInterface public interface Function<T, R> { R apply(T t);
default <V> Function<V, R> compose(Function<? super V, ? extends T> before) { Objects.requireNonNull(before); return (V v) -> apply(before.apply(v)); }
default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) { Objects.requireNonNull(after); return (T t) -> after.apply(apply(t)); }
static <T> Function<T, T> identity() { return t -> t; } }
2.Lambda
语法:类型可以省略写(因为有自动推导的功能,这也是为什么函数式接口只允许有一个抽象方法的原因),当执行语句只有一条时吗,可以将{}省略,并且将return关键字省去。除此之外,Lambda有延迟加载的功能,在某些场景下可以提升效率。
无参: ()->{ //执行语句 }
单参:(T t)->{ //执行语句 }
(t)->{ //执行语句 }
多参:(T t, K k)->{ //执行语句 }
1 /** 2 * @Created by zhenjun_gan 3 * @Date 2020/6/9 4 * 自定义函数式接口 5 */ 6 @FunctionalInterface 7 public interface MyFunction { 8 void myMethod(); 9 } 10 11 // 测试类 12 public class LambdaExample { 13 14 public static void main(String[] args) { 15 //传统的开启线程 16 new Thread(new Runnable() { 17 @Override 18 public void run() { 19 System.out.println("开启线程1"); 20 } 21 }).start(); 22 // Lambda简化 23 new Thread(() -> { 24 System.out.println("开启线程3"); 25 }).start(); 26 27 new Thread(() -> System.out.println("开启线程2")).start(); 28 29 //使用Lambda遍历集合 30 Arrays.asList(1, 2, 2, 4, 1, 66, 3, 778, 0).forEach((num) -> System.out.println(num)); 31 32 //测试函数式接口 33 int y = 12; 34 int x = 10; 35 String result1 = adder(x, y, new BiFunction() { 36 @Override 37 public Object apply(Object o, Object o2) { 38 return "" + x + y; 39 } 40 }); 41 //Lambda简化 42 String result3 = adder(x, y, (a, b) -> { 43 return "" + a + b; 44 }); 45 //省略 return 和{} 46 String result2 = adder(x, y, (a, b) -> "" + a + b); 47 System.out.println(result1);// 1012 48 System.out.println(result2);// 1012 49 System.out.println(result3);// 1012 50 51 // 延迟执行 52 testFunction(2, () -> System.out.println("执行function.myMethod...")); 53 } 54 //测试自定义的函数式接口 55 public static void testFunction(int a, MyFunction function) { 56 if (a == 1) { 57 System.out.println("执行testFunction..."); 58 function.myMethod(); 59 } 60 } 61 //做一个字符串的添加 62 public static String adder(Integer x, Integer y, BiFunction<Integer, Integer, String> fun) { 63 return fun.apply(x, y); 64 } 65 }
3.java8提供的常用函数式接口
Consumer<T>(消费)
Supplier<T>(生产)
Function<T,R>(转换)
Predicate<T>(断言)
1 class Person { 2 private String name; 3 public Person(String name) { 4 this.name = name; 5 } 6 // 重写equals ... 7 //getter and setter ... 8 } 9 10 import java.util.function.Consumer; 11 import java.util.function.Function; 12 import java.util.function.Predicate; 13 import java.util.function.Supplier; 14 /** 15 * @Created by zhenjun_gan 16 * @Date 2020/6/10 17 * 常用的函数式接口 18 */ 19 public class CommonFunctionLambdaExample { 20 21 public static void main(String[] args) { 22 23 Person person1 = testSupplier(() -> new Person("张三")); 24 System.out.println(person1);//Person{ name='张三'} 25 26 Person person2 = new Person("李四"); 27 testConsumer(person2, person -> System.out.println(person));//Person{ name='李四'} 28 29 String name = "王五"; 30 Person person3 = testFunction(name, pName -> new Person(pName));//Person{ name='王五'} 31 System.out.println(person3); 32 33 Person person = new Person("老刘"); 34 Person person4 = new Person("老刘"); 35 Person person5 = new Person("老王"); 36 System.out.println(testPredicate(person4, p -> person.equals(p)));//true 37 System.out.println(testPredicate(person5, p -> person.equals(p)));//false 38 } 39 40 // 生产一个Person对象(生产) 41 public static Person testSupplier(Supplier<Person> supplier) { 42 return supplier.get(); 43 } 44 45 // 消费一个Person对象(消费) 46 public static void testConsumer(Person person, Consumer<Person> consumer) { 47 consumer.accept(person); 48 } 49 50 //消费一个name生产一个Person(转换) 51 public static Person testFunction(String name, Function<String, Person> function) { 52 return function.apply(name); 53 } 54 55 //判断(断言) 56 public static boolean testPredicate(Person person, Predicate<Person> predicate) { 57 return predicate.test(person); 58 } 59 }
4.结语
java中的函数式接口其实单独使用并没有什么太大的意义,只是相比于传统的代码简化了而已,但是也降低了代码的可读性。Java中使用Lambda主要是为了与Stream结合,在实际工作中也是与Stream结合对数据进行一些操作,与传统的数据集操作相比更具优雅性,同时效率也更高。