31.2 Java进阶之lambda函数式接口

  • Post author:
  • Post category:java


学习总结自《java核心技术卷一》



1.函数式接口

我们前面已经说到,lambda表达式其实就是对接口方法的快速实现。

那是不是所有的接口方法都能让lambda表达式快速实现呢? 答案是否定的,

lambda表达式只能对特殊的接口方法进行快速实现,那就是函数式接口,lambda表达式能对函数式接口的方法进行快速实现。



1.1 什么是函数式接口?

对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个lambda表达式替代对象,这样的接口我们称之为

函数式接口(functional interface)

。(有的接口可能重新声明Object类的方法,这些声明可能会让方法不再是抽象的,且在javaSE8中,接口可以声明非抽象方法)



1.2 如何用lambda表达式替代?

我们以下面的例子来理解:

Arrays.sort(words,(first,second)->first.length()-second.length());

上面使用了Arrays.sort()方法,它的第二个参数需要一个Comparator的实例,而Comparator就是只有一个抽象方法的接口,

int compare(T o1, T o2);

所以我们可以用lambda表达式

(first,second)->first.length()-second.length()

替代它


我们要记住:把lambda表达式看作是一个函数,而且lambda表达式可以传递到函数式接口中去

实际上,在Java中lambda表达式所能做的也只能是转换为函数式接口:

例如下面的函数式接口

public interface ActionListener extends EventListener {

    /**
     * Invoked when an action occurs.
     */
    public void actionPerformed(ActionEvent e);

}

使用它

Timer t= new Timer(1000,(evnet)->
{
  System.out.println("At the tone,the time is"+new Date());
  Toolkit.getDefaultToolkit().beep();
});

上面代码与使用实现了ActionListener接口的类相比,这个代码可读性要好很多。

演示:

public static void main(String[] args) throws InterruptedException {
    Timer t = new Timer(1000, event->{
        System.out.println("At the tone,the time is"+new Date());
        Toolkit.getDefaultToolkit().beep();
    });
    t.start();
    JOptionPane.showMessageDialog(null,"要退出吗?");
    System.exit(0);

}

在这里插入图片描述



1.3 Java中常用函数式接口


Java API在java.util.function包中定义了很多非常通用的函数式接口。


在这里插入图片描述



1.3.1 Runnable接口

@FunctionalInterface
public interface Runnable {
    //抽象方法
    public abstract void run();
}

这个接口典型的应用场景就是多线程编程,它没有出参和入参,也没有泛型参数。

使用实例:

public void runnableStudy(Runnable runnable){
    runnable.run();
}
//测试
functionStudy.runnableStudy(()->{
    System.out.println("使用Runnable的lambada表达式打印这句话的");
});

在这里插入图片描述



1.3.2 Supplier接口

@FunctionalInterface
public interface Supplier<T> {
    T get();
}

可以看到,这个接口没入参,定义了一个泛型出参,我们可以根据需求去使用它。

例如:

public void supplierStudy(Supplier<String> stringSupplier){
    System.out.println(stringSupplier.get());
}



1.3.3 Consumer接口

@FunctionalInterface
public interface Consumer<T> {

    /**
     * Performs this operation on the given argument.
     *
     * @param t the input argument
     */
    void accept(T t);
}

这个接口提供了一个泛型入参,无出参的方法。

public void consumerStudy(String param,Consumer<String> stringConsumer){
    stringConsumer.accept(param);
}



1.3.4 BiConsumer接口

@FunctionalInterface
public interface BiConsumer<T, U> {

    /**
     * Performs this operation on the given arguments.
     *
     * @param t the first input argument
     * @param u the second input argument
     */
    void accept(T t, U u);
}

此函数式接口提供了两个泛型入参,无出参。

例如:

public void biConsumerStudy(String u, String t, 
BiConsumer<String,String> biConsumer){
    biConsumer.accept(u,t);
}



1.3.5 Function接口

@FunctionalInterface
public interface Function<T, R> {

    /**
     * Applies this function to the given argument.
     *
     * @param t the function argument
     * @return the function result
     */
    R apply(T t);
}
public void functionStudy(String t,Function<String,String> function){
    System.out.println(function.apply(t));
}



1.3.6 BiFunction接口

@FunctionalInterface
public interface BiFunction<T, U, R> {

    /**
     * Applies this function to the given arguments.
     *
     * @param t the first function argument
     * @param u the second function argument
     * @return the function result
     */
    R apply(T t, U u);
}
public void biFunctionStudy(String t, String u, BiFunction<String,String,String> biFunction){
    System.out.println(biFunction.apply(t,u));
}



1.3.7 UnaryOperator接口

@FunctionalInterface
public interface UnaryOperator<T> extends Function<T, T> {

    /**
     * Returns a unary operator that always returns its input argument.
     *
     * @param <T> the type of the input and output of the operator
     * @return a unary operator that always returns its input argument
     */
    static <T> UnaryOperator<T> identity() {
        return t -> t;
    }
}
public void unaryOperatorStudy(String s,UnaryOperator<String> unaryOperator){
    System.out.println(unaryOperator.apply(s));
}



1.3.8 BinaryOperator接口

@FunctionalInterface
public interface BinaryOperator<T> extends BiFunction<T,T,T> {
}
public void binaryOperatorStudy(String s,String t,BinaryOperator<String> binaryOperator){
    System.out.println(binaryOperator.apply(s,t));
}



1.3.9 Predicate接口

@FunctionalInterface
public interface Predicate<T> {

    /**
     * Evaluates this predicate on the given argument.
     *
     * @param t the input argument
     * @return {@code true} if the input argument matches the predicate,
     * otherwise {@code false}
     */
    boolean test(T t);
}
public void predicateStudy(String s,Predicate<String> predicate){
    if(predicate.test(s)){
        System.out.println("正确!!!!");
    }
}



1.3.10 BiPredicate接口

@FunctionalInterface
public interface BiPredicate<T, U> {

    /**
     * Evaluates this predicate on the given arguments.
     *
     * @param t the first input argument
     * @param u the second input argument
     * @return {@code true} if the input arguments match the predicate,
     * otherwise {@code false}
     */
    boolean test(T t, U u);
}
public void biPredicateStudy(String t,String u,BiPredicate<String,String> biPredicate){
    if(biPredicate.test(t,u)){
        System.out.println("正确!!");
    }
}



1.3.11 测试实例

public static void main(String[] args) {

    FunctionStudy functionStudy = new FunctionStudy();
    //无入参,出参lambda表达式
    functionStudy.runnableStudy(()->{
        System.out.println("使用Runnable的lambada表达式打印这句话的");
    });
    //无入参,有出参lambda表达式
    functionStudy.supplierStudy(()->{
        return "使用Supplier的lambada表达式打印这句话的";
    });
    //一个入参,无出参lambda表达式
    functionStudy.consumerStudy("consumerStudy",(s)->{
        if(s.contains("consumer")){
            System.out.println(s);
        }
    });
    //两个入参,无出参lambda表达式
    functionStudy.biConsumerStudy("BiConsumerStudy","two",(s,t)->{
        System.out.println(s+t);
    });
    //一个入参,有出参lambda表达式
    functionStudy.functionStudy("functionStudy",(s)->{
        return s+"test";
    });
    //两个入参,一个出参lambda表达式
    functionStudy.biFunctionStudy("bi","Function",(s,u)->{
        return s+u;
    });
    //一个入参,一个出参lambda表达式
    functionStudy.unaryOperatorStudy("s",(s)->{
        return s;
    });
    //两个入参,一个出参lambda表达式
    functionStudy.binaryOperatorStudy("binary","Operation",(s,v)->{
        return s+v;
    });
    //一个入参,指定boolean类型出参lambda表达式
    functionStudy.predicateStudy("isGood",(s)->{
        return s.contains("ood");
    });
    //两个入参,指定boolean类型出参lambda表达式
    functionStudy.biPredicateStudy("bi","Predicate",(t,u)->{
        if(t.equals("bi")&&u.contains("cate")){
            return true;
        }else
            return false;
    });
}

在这里插入图片描述



1.4 如何使用函数式接口

想要用lambda表达式做某些处理,还是要谨记表达式的用途,正确使用函数式接口,个人觉得Jdk中提供的一些函数式接口以及够用。

例如:java.util.function包中有一个接口:

public interface Predicate<T>{
 boolean test(T t);
}

ArrayList类有一个removeIf方法,它的参数就是一个Predicate。

public boolean removeIf(Predicate<? super E> filter)

这个接口专门用来传递lambda表达式。如:

list.removeIf(e->e==null);

上面的语句表示从一个数组列表删除所有的null值。



2 完整代码仓库地址


Java基础学习/src/main/java/Progress/exa31_2/FunctionStudy.java · 严家豆/Study – 码云 – 开源中国 (gitee.com)



版权声明:本文为c1776167012原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。