lambda表达式

函数式接口

@FunctionalInterface 用这个注解标注的接口就是函数式接口

特点

除了default方法和静态方法外,接口中只有一个方法

分类
  • 有参数有返回值 功能型
    public interface Function<T, R> {
        R apply(T t);
    }
  • 有参数无返回值 消费型
public interface Consumer<T> {
    void accept(T t);
}
  • 无参数有返回值 供给型
public interface Supplier<T> {
    T get();
}
  • 有参数返回布尔类型 断言型
public interface Predicate<T> {
    boolean test(T t);
}

lambda表达式

我们看一个简单的例子来感受下lambda相比于过去写法的便捷

        List<String> stringList = Arrays.asList("123", "121", "119", "134");
        //采用匿名内部类的形式
        stringList.sort(new Comparator<String>() {
            @Override
            public int compare(String o1, String o2) {
                return o1.compareTo(o2);
            }
        });
        //采用lambda的形式
        stringList.sort((s1, s2) -> s1.compareTo(s2));
写法

(args) -> {args相关具体操作}
说明 : args是接口中对应的参数(可以省略类型不写),多个可以用逗号隔开,如果只有一个参数()可以省略。具体操作部分如果只有一条语句{}可以省略。如果是有返回值的接口,并且操作只有一条语句{return}都可以省略

函数式接口用来为 Lambda 定义类型的

  • 例子
        Comparator<Apple> byColor2 = (o1, o2) -> o1.getColor().compareTo(o2.getColor());

        Function<String, Integer> flambda = s -> s.length();

        Predicate<Apple> p = (Apple a) -> a.getColor().equals("green");
        
        Predicate<Apple> p2 = a -> {return a.getColor().equals("red");}

method-references方法推导

看一个简单的例子

public static <T> void run(Consumer<T> consumer, T t) {
        consumer.accept(t);
    }
    public static void main(String[] args) {
        //lambda Consumer接口,有一个参数无返回值,只是输出
        run(x -> System.out.println(x), "hello");
        //method-references
        run(System.out::println, "world");
        //看一下println源码,也是有一个参数无返回值,这时候就可以使用method-references
        /**
         * Prints a String and then terminate the line.  This method behaves as
         * though it invokes <code>{@link #print(String)}</code> and then
         * <code>{@link #println()}</code>.
         *
         * @param x  The <code>String</code> to be printed.
         */
        public void println(String x) {
            synchronized (this) {
                print(x);
                newLine();
            }
        }
        }

再看一个方法推导的便捷例子

    List<Apple> apples = Arrays.asList(new Apple("red", 213), new Apple("green", 110)
                , new Apple("blue", 122));
        //采用lambda表达式 写法1
        apples.sort((a1,a2) -> a1.getColor().compareTo(a2.getColor()));
        // 写法2
        apples.sort(Comparator.comparing(x->x.getColor()));
        //使用method-references
        apples.sort(Comparator.comparing(Apple::getColor));
写法

类或者对象::方法名

        //1。通过一个类的静态方法进行推导
        int value = Integer.parseInt("456");
        Function<String, Integer> function = Integer::parseInt;
        Integer apply = function.apply("456");
        System.out.println(value == apply);
        
        //2.通过类的成员方法进行推导
        BiFunction<String, Integer, Character> function1 = String::charAt;
        Character character = function1.apply("hello", 1);
        System.out.println(character);
        
        //3.通过对象的普通方法进行推导
        String str = new String("world");
        Function<Integer, Character> function2 = str::charAt;
        Character character1 = function2.apply(2);
        System.out.println(character1);

我们回过头看下上面例子中Comparator.comparing的源码

public static <T, U extends Comparable<? super U>> Comparator<T> comparing(
            Function<? super T, ? extends U> keyExtractor)
    {
        Objects.requireNonNull(keyExtractor);
        return (Comparator<T> & Serializable)
            (c1, c2) -> keyExtractor.apply(c1).compareTo(keyExtractor.apply(c2));
    }

可以发现它的入参是一个Function接口,值得注意的是虽然我public String getColor()是个无参有返回值的接口,但是采用类::普通方法这种形式写的时候,相当于传入一个类的对象,所以用Function来接收

    Function<Apple, String> getColor = Apple::getColor;

如果我采用对象::方法,就可以用Supplier接口来接收了

        Apple apple = new Apple("red", 213);
        Supplier<String> supplier = apple::getColor;
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值