zoukankan      html  css  js  c++  java
  • JAVA8 Lambda表达式

    简介

    在函数式编程中函数可以在程序中传来传去,甚至数字也可以用函数表示,而在面向对象中必须将这些函数封装成方法,通过调用方法实现。所以 Java 从邻居那拿来了 Lambda。

    Java8 引入了 Lambda 表达式,它使代码变得更简洁和高效,更方便的让我们在计算机上说话,长得就像下面那样。

    s -> s + s;
    (s1, s2) -> { return s1 + s2; };
    

    Lambda可以用于实现只有一个抽象方法的接口,在接口加上 @FunctionalInterface 注解可以提醒我们接口只有一个抽象方法 。下面是 Java 的 Comparator 两种实现方式,以前的写法是实现一个匿名类。

    //comparator2 更简洁
    Comparator<String> comparator1 = (s1, s2) -> s1.compareTo(s2);
    Comparator<String> comparator2 = String::compareTo;
    

    几种常见函数

    Java 本身提供了 Function、BiFunction、Predicate、Consumer、Supplier 等几种函数,介绍如下。

    函数 格式 说明
    Function Function<T, R> 接收一个参数,有一个返回值
    BiFunction BiFunction<T, U, R> 接收两个参数,有一个返回值
    Predicate Predicate<T> 接收一个参数,返回值boolean类型
    Consumer Consumer<T> 接收一个参数,没有返回值
    Supplier Supplier<T> 没有参数,有一个返回值

    Function

    Function<T, R> 中 T 是传入参数的类型,R 是返回值的类型。源码中主要有 apply、compose、andThen 方法。

    @FunctionalInterface
    public interface Function<T, R> {
    
        //执行函数
        R apply(T t);
    
        //先执行 before 函数,再执行当前函数。
        default <V> Function<V, R> compose(Function<? super V, ? extends T> before) {
            Objects.requireNonNull(before);
            return (V v) -> apply(before.apply(v));
        }
    
        //先执行当前函数,再执行 after 函数
        default <V> Function<T, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t) -> after.apply(apply(t));
        }
    }
    

    示例如下。

    Function<Integer, String> fun1 = integer -> String.valueOf(integer + integer);
    Function<String, BigDecimal> fun2 = s -> new BigDecimal(s + ".5");
    //执行函数
    String s = fun1.apply(1);
    //两个函数中都是 fun1 先执行
    BigDecimal decimal1 = fun1.andThen(fun2).apply(1);
    BigDecimal decimal2 = fun2.compose(fun1).apply(1);
    

    执行后 s 值是 2,decimal1 和 decimal2 值是 2.5。

    BiFunction

    BiFunction<T, U, R> 中 T 和 U 是传入的参数类型,R 是返回值类型。源码中有 apply、andThen 方法,因为 BiFunction 需要两个参数,所以没有 compose 方法。

    @FunctionalInterface
    public interface BiFunction<T, U, R> {
        //执行方法
        R apply(T t, U u);
        //先执行当前函数,再执行 after 函数
        default <V> BiFunction<T, U, V> andThen(Function<? super R, ? extends V> after) {
            Objects.requireNonNull(after);
            return (T t, U u) -> after.apply(apply(t, u));
        }
    }
    

    示例如下。

    BiFunction<Integer, Integer, String> biFunction = (param1, param2) -> String.valueOf(param1 * param2 + 1);
    Function<String, BigDecimal> fun1 = s -> new BigDecimal(s + ".5");
    //先执行 biFunction,再执行 fun1
    BigDecimal decimal3 = biFunction.andThen(fun1).apply(1, 2);
    

    Predicate

    Predicate<T> 中 T 是 传入参数的类型,返回一个 boolean 类型的值。源码中主要有 test、and、negate、or、isEqual 方法。

    @FunctionalInterface
    public interface Predicate<T> {
        //执行方法
        boolean test(T t);
        //关系运算符 &&,当 test 的结果为 false 时直接结束,不运算 other
        default Predicate<T> and(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) && other.test(t);
        }
        //关系运算符 !
        default Predicate<T> negate() {
            return (t) -> !test(t);
        }
    	//关系运算符 ||,当 test 的结果为 true 时直接结束,不运算 other
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
        //判断相等
        static <T> Predicate<T> isEqual(Object targetRef) {
            return (null == targetRef)
                    ? Objects::isNull
                    : object -> targetRef.equals(object);
        }
    }
    

    示例如下。

    //为空返回 true
    Predicate<String> isNull = Objects::isNull;
    //不为空返回 true
    Predicate<String> nonNull = Objects::nonNull;
    boolean bool = isNull.or(nonNull.negate()).and(Predicate.isEqual("123")).test("123");
    

    执行后 bool 的值为 false,执行后 isNull.test() 为 false,nonNull.negate() 为 false,因为最后一个是 and,所以不需要判断 Predicate.isEqual("123"),最后得出 false || false 为 false。如果 and 之后还有 or 的话要接着判断。

    Consumer

    Consumer<T> 中 T 是传入参数的类型,没有返回值。源码中有 accept 和 andThen 方法。

    @FunctionalInterface
    public interface Consumer<T> {
        //执行方法
        void accept(T t);
        //先执行当前函数,再执行 after 函数
        default Consumer<T> andThen(Consumer<? super T> after) {
            Objects.requireNonNull(after);
            return (T t) -> { accept(t); after.accept(t); };
        }
    }
    

    示例如下。

    Consumer<Integer> consumer1 = integer -> System.out.println(integer + 1);
    Consumer<Integer> consumer2 = integer -> System.out.println(integer + 2);
    //先执行 consumer1,再执行 consumer2
    consumer1.andThen(consumer2).accept(1);
    

    执行后控制台依次打印 2 和 3。

    Supplier

    Supplier<T> 中 T 是返回值的类型,没有传入的参数。源码中只有 get 方法。

    @FunctionalInterface
    public interface Supplier<T> {
        //执行方法
        T get();
    }
    

    示例如下。

    Supplier<LocalDate> supplier = LocalDate::now;
    //返回当前日期
    LocalDate localDate = supplier.get();
    System.out.println(localDate);
    

    控制台打印当前日期时间 2020-05-31。

    总结

    本文对 Java8 中的 lambda 做了简单了解,介绍了 5 种函数,想熟练使用还需要实践(第一次写博客,有不足还请指正)。

    参考资料

    深入浅出 Java 8 Lambda 表达式

    Execution in the Kingdom of Nouns

    函数式编程中的重要概念

  • 相关阅读:
    oracle 中增加、修改、删除字段
    Oracle 中int , number的区别
    [转]信息系统项目管理师考试论文写作技巧
    项目论证
    java中异步计算之Future
    vmstat例子
    页面重构工作者的必备素质,转载
    办公室人员对号入座太经典啦!
    大家多注意身体!
    经典!牛人汽车防盗秘笈
  • 原文地址:https://www.cnblogs.com/hligy/p/12996875.html
Copyright © 2011-2022 走看看