Lambda方法引用

inventory.sort((Apple c1, Apple c2) -> c1.getWeight().compareTo(c2.getWeight()));

与下面的代码是等同的

inventory.sort(Comparator.comparing(Apple::getWeight));


这里把(Apple c1, Apple c2) -> c1.getWeight().compareTo(c2.getWeight()) 简化成了Comparator.comparing(Apple::getWeight()),这种写法被专家们认为更自然、更易读。完整代码如下:

package com.qingke.chapter2;

import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;

public class Lambda { public static void main(String[] args) {
        List<Apple> inventory = new ArrayList<>();
        Apple a1 = new Apple();
        a1.setColor("green");
        a1.setWeight(48);
        Apple a2 = new Apple();
        a2.setColor("red");
        a2.setWeight(89);
        Apple a3 = new Apple();
        a3.setColor("green");
        a3.setWeight(79);
        inventory.add(a1);
        inventory.add(a2);
        inventory.add(a3);

        inventory.sort(Comparator.(Apple::getWeight));

        inventory.stream().forEach( (Apple p) -> System..println(p.getWeight() + " " + p.getColor()));
    }
}


同样推展:

(Apple a) -> a.getWeight()   ====>    Apple::getWeight

() -> Thread.currentThread().dumpStack()   ====>   Thread.currentThread()::dumpStack

(str, i) -> str.substring(i)   ====>  String.substring

(String s) -> System.out.println(s)   ====>   System.out::println

这里面分涉及到如下几种类别:

(1)静态方法的引用 

         Integer::parseInt,其中parseInt()为Integer类的静态方法

(2)对象(类的实例对象)方法的引用

         Transaction expensiveTransaction = .....;

         expensiveTransaction::getValue,其中expensiveTransaction为Transaction类的一个实例,getValue()为Transaction的方法

(3)指向任意类型实例方法的引用

         这个比较难理解,

         类似String::length,你在引用一个对象的方法,而这个对象本身是Lambda的一个参数; 

         再如,(String s) -> s.toUpperCase()   ====>   String::toUpperCase

第(2)和第(3)的区别在于,(2)是Lambda表达式之外的对象方法引用、(3)是Lambda表达式之内的对象方法引用


List<String> str = Arrays.("a", "A", "b", "B", "E", "D");
str.sort((s1, s2) -> s1.compareToIgnoreCase(s2)); 
str.stream().forEach((s) -> System..println(s));

上面可以是按描述来调用,Java8更期望是按方法来调用,所以修改为:

List<String> str = Arrays.("a", "A", "b", "B", "E", "D");
str.sort(String::compareToIgnoreCase);
str.stream().forEach(System.::println);


再例如:把字符串类型的数字转换为数字型的数字

Function<String, Integer>  = (String s) -> Integer.(s);
System..println(.apply("8"));

按方法引用可修改为:

Function<String, Integer> stringToInteger = 
System..println(stringToInteger.apply("8"));


再例如:判断集合中是否有该元素

BiPredicate<List<String>, String> contains = ;
List<String> strList = Arrays.("a", "b", "china", "love", "c", "demo");
System..println(contains.test(strList, "china"));

按方法引用可修改为:

BiPredicate<List<String>, String> contains = ;
List<String> strList = Arrays.("a", "b", "china", "love", "c", "demo");
System..println(contains.test(strList, "china"));


2. 构造函数引用

我们以前定义一个Apple类,若对类进行初始化通常会这样操作:

public class Apple {
    private String color;

    private int weight;

    public String getColor() {
        return color;
    }

    public void setColor(String color) {
        this.color = color;
    }

    public int getWeight() {
        return weight;
    }

    public void setWeight(int weight) {
        this.weight = weight;
    }
}

Apple a = new Apple();

这样通过Apple的实例对象a就可以去干活了。但自从引入了Lambda之后,我们也可以这样操作:

Supplier<Apple> c1 = () -> new Apple(); 
Apple a = c1.get();

这里使用了描述符:() -> new Apple()来生成对象,当然这里再讲构造器函数引用,所以上面可修改为:

Supplier<Apple> c1 = ;
Apple a = c1.get();


如果Apple的构造函数是:

public Apple(int weight){ // 带参数

     this.weight = weight;

}

则构造函数引用可以这样写:

Function<Integer, Apple> c2 = Apple::new;
Apple a2 = c2.apply(110);

它等价于:

Function<Integer, Apple> c2 = (weight) -> new Apple(weight);

Apple a2 = c2.apply(110);


猜你喜欢

转载自blog.51cto.com/qingkechina/2554685