常用函数式接口的学习

定义

有且仅有一个抽象方法的接口称之为“函数式接口”,但是“函数式接口”依旧可以包含其它的非抽象方法,例如,默认方法、静态方法、私有方法等。关于什么是默认方法、静态方法、私有方法请参见《Java声明定义抽象类_接口_继承_实现

函数式接口的实现类对象,可以通过 Lambda 表达式来构造。

常用的函数式接口

java.util.function 包下有很多 JDK 提供的函数式接口。

Supplier

java.util.function.Supplier<T>,接口包含一个无参的方法:public abstract T get()。用来获取一个泛型参数指定类型的对象数据。由于这是一个函数式接口,也就意味着对应的 Lambda 表达式需要“对外提供”一个符合泛型类型的对象数据。

public interface Supplier<T>,称之为生产型接口,指定接口的泛型是什么类型,那么接口中的方法就会返回(好像生活中的生产)什么类型的数据。

演示代码

package priv.lwx.javaprac.functionalinterface;

import java.util.function.Supplier;

/**
 * @ClassName Demo04Supplier
 * @Description 函数式接口Supplier的演示代码
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/7 下午4:40
 */
public class Demo04Supplier {
    
    
    public static void main(String[] args) {
    
    
        System.out.println(getString(() -> "杨思敏"));
    }

    public static String getString(Supplier<String> sup) {
    
     // 接口指定了泛型的具体数据类型,相关抽象方法涉及到的泛型的具体数据类型就确定了,实现类就需要根据已确定的数据类型来实现抽象方法
        return sup.get();
    }
}

Consumer

java.util.function.Consumer<T>,该接口正好与 Supplier<T> 接口相反,它不是生产一个数据,而是消费一个数据,其数据类型由泛型来决定。

accept 方法

Consumer<T> 接口中含有一个抽象方法 public abstract void accept(T t),用来消费一个指定泛型类型的数据,所谓消费数据就是使用数据,例如,打印输出、计算等

演示代码

package priv.lwx.javaprac.functionalinterface;

import java.util.function.Consumer;

/**
 * @ClassName Demo16Consumer
 * @Description TODO
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/10 下午2:56
 */
public class Demo16Consumer {
    
    
    public static void main(String[] args) {
    
    
        // 定义一个字符串数组,存放姓名
        String[] names = {
    
    "潘金莲", "李瓶儿", "武媚娘"};
        // 调用方法printArray,将数组内容打印输出
        printArray(names, (t) -> {
    
    
            for (String s : t) {
    
    
                System.out.println(s);
            }
        });

    }

    // 定义一个方法用来打印输出字符串数组的内容,传入两个参数:字符串数组、Consumer对象(即Lambda表达式)
    public static void printArray(String[] strs, Consumer<String[]> action) {
    
    
        action.accept(strs);
    }
}

andThen 方法

源代码如下所示:

default Consumer<T> andThen(Consumer<? super T> after) {
    
    
	Objects.requireNonNull(after);
	return (T t) -> {
    
     this.accept(t); after.accept(t); };
}

return (T t) -> { this.accept(t); after.accept(t); } 这行代码做了下面几件事

扫描二维码关注公众号,回复: 14243746 查看本文章

1.在某个方法体内去定义另外一个方法(实现 Consumer 的抽象方法 accept),目前也就是只有 Lambda 表达式可以这样做了
2.创建了一个对象,即接口 Consumer 的实现类对象
3.this 是指执行方法 andThen 时的当前对象,并不是执行方法 accept 时的当前对象
4.执行方法 andThen 时,就已经确定了 this 的身份,所以这里要特别注意,不要被绕进去了

注意:Lambda 表达式的实现类并没有生成单独的类文件,所以实现方法的代码应该还在外部类(宿主类)中

演示代码

package priv.lwx.javaprac.functionalinterface;

import java.util.function.Consumer;

public class Demo05Consumer {
    
    
    public static void main(String[] args) {
    
    
        String str = "刘德华";

        // 泛型接口声明的变量接收实现类的对象,必须指明具体的数据类型,换句话说,使用Lambda表达式创建对象必须指定具体的数据类型
        Consumer<String> con1 = t -> System.out.println(t); // 这是对accept方法的一种实现,打印输出字符串
        Consumer<String> con2 = t -> System.out.println(t.length()); // 这是对accept方法的另外一种实现,输出字符串的长度

        // andThen方法返回的是另外一个实现类的对象,和对象con1和con2分属三个不同的实现类
        // 这个实现类对accept方法进行了另外一种实现,就是调con1的accept方法,调con2的accept方法,具体看方法andThen的源代码
        // 下面这行代码其实执行了三个Consumer对象的accept方法,且它们分属不同的实现类,因此方法accept也是不同的实现,只是名称相同而已
        con1.andThen(con2).accept(str); // 输出的结果是:刘德华 3
    }
}

Predicate

test 方法

含有一个抽象方法:
public abstract boolean test(T t),用来对指定的数据进行判断,符合条件返回 true,不符合返回 false

and 方法

表示“并且”关系,实现逻辑关系中的“与”,将多个 Predicate 对象所代表的条件进行“与”运算。
“与”运算符为“&&”。

演示代码

package priv.lwx.javaprac.functionalinterface;

import java.util.function.Predicate;

/**
 * @ClassName Demo08Predicate
 * @Description Predicate的and方法演示代码
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/8 下午9:17
 */
public class Demo08Predicate {
    
    
    public static void main(String[] args) {
    
    
        String str = "sdfdsafds";

        /*
        判断字符串的长度是否大于5,并且包含小写字母a,
        如果两个条件都满足返回true,否则返回false
         */
        boolean b = checkString(str, (t) -> {
    
    
            return t.length() > 5;
        }, (t) -> {
    
    
            return t.contains("a");
        });

        System.out.println(b);
    }


    /**
     * @return boolean
     * @MethodName checkString
     * @Author liaowenxiong
     * @Description 声明定义一个方法,用于传递一个字符串和两个条件,
     * 判断指定的字符串,如果两个条件都满足则返回true,否则返回false
     * @Date 下午9:24 2021/9/8
     * @Param [str, p1, p2]
     */
    public static boolean checkString(String str, Predicate<String> p1, Predicate<String> p2) {
    
    
        boolean b = p1.and(p2).test(str);
        return b;
    }
}

or 方法

表示“或者”关系,实现逻辑关系中的“或”,将多个 Predicate 对象所代表的条件进行“或”运算。
“或”运算符为“||”。

negate 方法

实现逻辑关系中的“非”,将多个 Predicate 对象所代表的条件进行“非”运算。
“非”也可以称之为“取反”,非真就是假,非假就是真。
“非”运算符为“!”。

Function

java.util.function.Function<T,R>,接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。

apply 方法

public abstract R apply(T t),根据类型 T 的参数获取类型 R 的结果。
使用的场景,例如,将 String 类型转换为 Integer 类型。

演示代码

package priv.lwx.javaprac.functionalinterface;

import java.util.function.Function;

/**
 * @ClassName Demo14Function
 * @Description java.util.function.Function<T, R>,接口用来根据一个类型的数据得到
 * 另一个类型的数据,前者称为前置条件,后者称为后置条件。
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/9 下午1:35
 */
public class Demo14Function {
    
    
    public static void main(String[] args) {
    
    

        String str = "250";

        // 调用方法toInteger,传递字符串和一个Lambda表达式
        int i = toInteger(str, (t) -> {
    
    
            return Integer.valueOf(t);
        });

        System.out.println(i);
    }

    /**
     * 定义一个方法,方法的参数传递一个字符串类型的整数,再传递一个Function对象,
     * 泛型使用<String,Integer>,使用Function对象的方法apply,把字符串类型的
     * 整数转换为Integer类型的整数,并返回该整数
     */

    public static Integer toInteger(String str, Function<String, Integer> func) {
    
    
        Integer i = func.apply(str);
        return i;
    }

}

andThen 方法

先将一种类型的数据转换成另外一种类型的数据,再将另外一种类型的数据转换成其它类型,以此类推

演示代码

package priv.lwx.javaprac.functionalinterface;

import java.util.function.Function;

/**
 * @ClassName Demo15Function
 * @Description 需求:
 * 把String类型的"123"转换成Integer类型,把转换后端结果加10,
 * 把增加后的Integer数据,再转换成String
 * @Author liaowenxiong
 * @Version 1.0
 * @date 2021/9/9 下午3:10
 */
public class Demo15Function {
    
    
    public static void main(String[] args) {
    
    
        String str = "123";
        // 调用方法computerStringInteger,传入要计算的字符串整数和"加数"
        String r = addStringInteger(str, 10);
        System.out.println(r);

    }

    /**
     * 定义一个方法,对指定字符串型的整数进行加法计算并返回增加后的字符串
     * 此方法接收两个参数:
     * 1.字符串类型的整数
     * 2.整数型的加数
     */
    public static String addStringInteger(String str, int i) {
    
    
        Function<String, Integer> func = (t) -> {
    
    
            // 将字符串数据转换成Integer类型的数据,再加上参数 i
            return Integer.parseInt(t) + i;
        };

        Function<Integer, String> func2 = (t) -> {
    
    
            // 将Integer类型的数据,转换成字符串类型
            return Integer.toString(t);
        };

        // 将字符串转换成Integer,再转换成字符串返回
        return func.andThen(func2).apply(str);
    }
}

猜你喜欢

转载自blog.csdn.net/liaowenxiong/article/details/120154166
今日推荐