美文网首页
Java8特性学习笔记(二) 函数式接口

Java8特性学习笔记(二) 函数式接口

作者: 简单一点点 | 来源:发表于2021-12-23 18:25 被阅读0次

    本部分介绍一下Java 8中的函数式接口。

    主要参考以下两个项目:

    简介

    函数式接口(Functional Interface)就是一个有且仅有一个抽象方法,但是可以有多个非抽象方法的接口。

    Java 8增加了一种特殊的注解 @FunctionalInterface,但是这个注解通常不是必须的(某些情况建议使用),只要接口只包含一个抽象方法,虚拟机会自动判断该接口为函数式接口。一般建议在接口上使用 @FunctionalInterface 注解进行声明,这样的话,编译器如果发现你标注了这个注解的接口有多于一个抽象方法的时候会报错的,

    函数式接口可以被隐式转换为 lambda 表达式。

    函数式接口例子

    首先我们写个函数式接口的例子来感受下。

    @FunctionalInterface
    public interface Converter<F, T> {
      T convert(F from);
    }
    

    用lambda表达式实现这个接口。

    Converter<String, Integer> converter = (from) -> Integer.valueOf(from);
    Integer converted = converter.convert("123");
    System.out.println(converted.getClass()); //class java.lang.Integer
    System.out.println(converted); // 123
    

    内置函数式接口

    Java8 之前已有的函数式接口:

    • java.lang.Runnable
    • java.util.concurrent.Callable
    • java.security.PrivilegedAction
    • java.util.Comparator
    • java.io.FileFilter
    • java.nio.file.PathMatcher
    • java.lang.reflect.InvocationHandler
    • java.beans.PropertyChangeListener
    • java.awt.event.ActionListener
    • javax.swing.event.ChangeListener

    Java8 新增加的函数接口:

    • java.util.function

    下面重点介绍 java.util.function 中比较常用的函数式接口。

    Predicate

    Predicate 接口是只有一个参数的返回布尔类型值的断言型接口。该接口包含多种默认方法来将 Predicate 组合成其他复杂的逻辑(比如:与,或,非)。

    该接口可以用于流的筛选。给定一个包含若干项的流,Stream 接口的 filter方法传入一个 Predicate 并返回一个新的流,它仅包含满足给定谓词的项。

    接口提供如下方法:

    方法 描述
    default Predicate and(Predicate<? super T> other) 接收一个Predicate类型,也就是将传入的条件和当前条件以并且的关系过滤数据。
    static Predicate isEqual(Object targetRef) 返回根据 Objects.equals(Object, Object)测试两个参数是否相等的谓词。
    default Predicate negate() 返回表示此谓词的逻辑否定的谓词。
    default Predicate or(Predicate<? super T> other) 接收一个Predicate类型,将传入的条件和当前的条件以或者的关系过滤数据。
    boolean test(T t) 在给定的参数上评估这个谓词。

    接口使用示例:

    Predicate<String> predicate = (s) -> s.length() > 0;
    
    predicate.test("foo");              // true
    predicate.negate().test("foo");     // false
    
    Predicate<Boolean> nonNull = Objects::nonNull;
    Predicate<Boolean> isNull = Objects::isNull;
    
    Predicate<String> isEmpty = String::isEmpty;
    Predicate<String> isNotEmpty = isEmpty.negate();
    

    接口源码:

    package java.util.function;
    import java.util.Objects;
    
    @FunctionalInterface
    public interface Predicate<T> {
        
        // 该方法是接受一个传入类型,返回一个布尔值.此方法应用于判断.
        boolean test(T t);
    
        //and方法与关系型运算符"&&"相似,两边都成立才返回true
        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);
        }
        //or方法与关系型运算符"||"相似,两边只要有一个成立就返回true
        default Predicate<T> or(Predicate<? super T> other) {
            Objects.requireNonNull(other);
            return (t) -> test(t) || other.test(t);
        }
       // 该方法接收一个Object对象,返回一个Predicate类型.此方法用于判断第一个test的方法与第二个test方法相同(equal).
        static <T> Predicate<T> isEqual(Object targetRef) {
            return (null == targetRef)
                    ? Objects::isNull
                    : object -> targetRef.equals(object);
        }
    }
    

    Function

    Function 接口接受一个参数并生成结果。默认方法可用于将多个函数链接在一起(compose, andThen)。

    接口提供如下方法:

    方法 描述
    default Function<T,V> andThen(Function<? super R,? extends V> after) 返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果(先执行当前对象的apply方法,再执行after对象的方法)。
    R apply(T t) 将此函数应用于给定的参数。
    default Function<V,R> compose(Function<? super V,? extends T> before) 返回一个组合函数,首先将 before函数应用于其输入,然后将此函数应用于结果(先执行before对象的apply,再执行当前对象的apply,将两个执行逻辑串起来)。
    static Function<T,T> identity() 返回一个总是返回其输入参数的函数。

    接口使用示例:

    Function<String, Integer> toInteger = Integer::valueOf;
    Function<String, String> backToString = toInteger.andThen(String::valueOf);
    System.out.println(backToString.apply("123"));     // "123"
    

    接口源码:

    package java.util.function;
     
    import java.util.Objects;
     
    @FunctionalInterface
    public interface Function<T, R> {
        
        //将Function对象应用到输入的参数上,然后返回计算结果。
        R apply(T t);
        //将两个Function整合,并返回一个能够执行两个Function对象功能的Function对象。
        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;
        }
    }
    

    Supplier

    Supplier 接口产生给定泛型类型的结果。 与 Function 接口不同,Supplier 接口不接受参数。

    接口方法:

    方法 描述
    T get() 获得结果

    接口示例:

    Supplier<Person> personSupplier = Person::new;
    personSupplier.get();   // new Person
    

    这个接口的作用是可以把耗资源运算放到 get 方法里,在程序里,我们传递的是 Supplier 对象,直到调用 get 方法时,运算才会执行。这就是所谓的惰性求值。

    Consumer

    Consumer 接口表示要对单个输入参数执行的操作。

    接口方法:

    方法 描述
    void accept(T t) 对给定的参数执行此操作
    default Consumer andThen(Consumer<? super T> after) 返回一个组合的 Consumer ,按顺序执行该操作,然后执行 after操作(用于函数复合)

    接口示例:

    Consumer<Person> greeter = (p) -> System.out.println("Hello, " + p.firstName);
    greeter.accept(new Person("Luke", "Skywalker"));
    

    相关文章

      网友评论

          本文标题:Java8特性学习笔记(二) 函数式接口

          本文链接:https://www.haomeiwen.com/subject/vxfkqrtx.html