首页 > 技术文章 > Java学习笔记_Lambda学习

CoderGan 2020-06-11 21:05 原文

  在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 }
Lambda例子代码

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结合对数据进行一些操作,与传统的数据集操作相比更具优雅性,同时效率也更高。

推荐阅读