lambda表达式

(o1,o2)->Integer.compare(o1,o2);
//example 1:  不用lambda表达式
      Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
      };
      System.out.println(comparator.compare(71, 22));  // result:1
//example 2:  用lambda表达式
        Comparator<Integer> comparator1 = (o1, o2) -> Integer.compare(o1,o2);
        System.out.println(comparator1.compare(22, 22));  // result:0
//example 3:  用方法引用
        Comparator<Integer> comparator2 = Integer ::compare;
        System.out.println(comparator2.compare(11, 44));  // result:0
  • 格式:
    ->左边:lambda的形参列表(接口中抽象方法的形参列表)
    ->右边:lambda体(重写的抽象方法的方法体)
    lambda本质:接口的实例
  • lambda使用:
    ->左边:lambda的形参中参数类型可以省略,其中只有一个参数,可以省区小括号()
    ->右边:lambda体 用{}包裹,若:lambda只有一条执行语句,则{}可以省略,若是return 语句,则省略{}时,必须省略return关键字。
//1. 无参
      Runnable runnable = new Runnable() {
            @Override
            public void run() {
                System.out.println("ddd");
            }
        };
        runnable.run();  //调用run()方法

        Runnable runnable1 = () -> System.out.println("ddd"); //lambda
        runnable1.run();    
//2. 有一个参数,没有返回值
      Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println("consumer--" + s);
            }
        };
        consumer.accept("abc");  //result:consumer--abc
        //Consumer<String> consumer1 = (String s) -> {
        Consumer<String> consumer1 = (s) -> {  //省去String,叫做类型推断
            System.out.println("consumer--" + s);
        };
        consumer1.accept("123");  //result: consumer--abc
        //当lambda体只有一句语句时 {} 可以省略
        Consumer<String> consumer2 = (s) -> System.out.println("consumer--" + s);;  
        consumer2.accept("456");  //result: consumer--456

// 3. 参数类型只有一个,()可以省略
      Consumer<String> consumer1 = s -> {  //省去()
            System.out.println("consumer--" + s);
        };
        consumer1.accept("123");  //result: consumer--abc
// 4. 只有一条执行语句,则{}可以省略,若是`return `语句,则省略{}时,必须省略`return`关键字。
      Comparator<Integer> comparator3 = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return o1 + o2;
            }
        };
        System.out.println(comparator3.compare(1, 2)); //result: 3

        Comparator<Integer> comparator4 = (o1,o2) -> o1 + o2;
        System.out.println(comparator4.compare(1, 3)); ////result: 4
  • 对于只有一个抽象方法的接口, 需要这种接口的对象时, 就可以提供一个 lambda 表达式。 这种接口称为函数式接口 (functional interface )
    函数式接口:
//1. Consumer<T>
@FunctionalInterface
public interface Consumer<T> {
      void accept(T t);
      default Consumer<T> andThen(Consumer<? super T> after){
            //see resource code
      }
}
//2. Supplier<T>
@FunctionalInterface
public interface Supplier<T> {

    T get();
}
// 3. Function<T, R>
@FunctionalInterface
public interface Function<T, R> {

    R apply(T t);
    ...
}
// 4. Predicate<T>
@FunctionalInterface
public interface Predicate<T> {

    boolean test(T t);
    default Predicate<T> and(Predicate<? super T> other) {}
    default Predicate<T> negate(){}
    default Predicate<T> or(Predicate<? super T> other){}
    static <T> Predicate<T> isEqual(Object targetRef){}
}
  • 方法引用:
object::instanceMethod
Class::staticMethod
Class::instanceMethod 

在前 2 种情况中, 方法引用等价于提供方法参数的 lambda 表达式。 如:System.out::println 等价于 x-> System.out.println(x)。 类似地,Math::pow 等价于(x,y)-> Math.pow(x, y)。
对于第 3 种情况, 第 1 个参数会成为方法的目标。例如,String::compareToIgnoreCase
同于 (x, y)-> x.compareToIgnoreCase(y)

/**
  ① Consumer中的 void accept(T t);
  ② PrintStream中的 println(T t); 
 要求:①中的参数列表和②中参数列表一样,①中的返回值和②中的返回值一样
*/
//1. object::instanceMethod
      Consumer<String> consumer = new Consumer<String>() {
            @Override
            public void accept(String s) {
                System.out.println(s);
            }
        };
        consumer.accept("abc");  //result: abc

        PrintStream ps = System.out;
        Consumer<String> consumer1 = ps::println; 
        consumer1.accept("ddd");  //result: ddd
/**
Comparator中的int compare(T t1, T t2);
Integer中的 int compare(T t1, T t2) 参数列表和返回值一样
*/
// 2. Class::staticMethod
      Comparator<Integer> comparator = new Comparator<Integer>() {
            @Override
            public int compare(Integer o1, Integer o2) {
                return Integer.compare(o1,o2);
            }
        };
        System.out.println(comparator.compare(22, 22));  //result: 0

        Comparator<Integer> comparator1 = Integer::compare;  
        System.out.println(comparator1.compare(23, 32));   //result: -1
/**
Comparator中的int compare(T t1, T t2);
String 中的 int compareTo(T t);        
*/
// 3. Class::instanceMethod
        Comparator<String> comparator = (o1, o2) -> o1.compareTo(o2);
        System.out.println(comparator.compare("df", "fd"));  //result: -2

        Comparator<String> comparator1 = String::compareTo;
        System.out.println(comparator1.compare("df", "df")); //result: 0
  • 构造器引用:和方法引用类似,函数式接口的抽象方法的形参列表和构造器的形参列表一致,抽象方法的返回值类型即为构造器所属的类的类型。如:Person :: new ,它是Person构造器的一个引用。
  • 数组引用:将数组看成一个类即可。就和构造器一样了。如:int[] :: new,相当于lambda表达式的 length -> new int[Length]
  • 变量作用域:
public static void repeat(String text, int count){
      for (int i = 1; i <= count; i++){
            ActionListener listener = event ->{
                  System.out.pn'nt1n(i + ": " + text);
                  // Error: Cannot refer to changing i
                  };
            new Timer(1000, listener).start();
            }
      }
}

这里有一条规则:lambda 表达式中捕获的变量必须实际上是最终变量 ( effectivelyfinal)。实际上的最终变量是指, 这个变量初始化之后就不会再为它赋新值。在这里,text 总是指示同一个 String 对象,所以捕获这个变量是合法的。不过,i 的值会改变,因此不能捕获 i。

posted @ 2021-01-13 10:41  先生胡  阅读(46)  评论(0编辑  收藏  举报