Java教程

JavaSE基础day27 函数型接口Funtion、断言型接口Predicate、方法引用

本文主要是介绍JavaSE基础day27 函数型接口Funtion、断言型接口Predicate、方法引用,对大家解决编程问题具有一定的参考价值,需要的程序猿们随着小编来一起学习吧!

 

一. 函数式接口

(一) 函数型接口

1、Function<T, R>: 函数型接口

2、抽象方法:R apply(T t) 方法提供把一个数据类型转换为另一个数据类型的规则

3、作用:

       如果需要定义一个函数,接收一个数据,将数据进行处理,完成之后,还能返回一个结果,就可以使用函数型接口,以前我们只能传递处理好之后的数据,或者将原始数据传入方法,现在可以传入处理方式

4、提供其他功能:

       Function andThen(Function f):在调用者处理方式之后,再进行参数的处理方式调用

 

案例1 : 定义一个方法功能, 根据整数x,计算出对应整数y, x数据由客户给出, y数据的计算方式根据客户要求决定

1) 客户1 : y为x的2倍

2) 客户2 : y与x相等

3) 客户3 : y为x的平方

4) ...

 

 

 案例2 : 定义一个方法功能, 根据字符串x,计算出对应整数y, x数据由客户给出, y数据的计算方式根据客户要求决定

1) 客户4 : x为”6” , 计算出x转换成整数后, 2倍结果

2) 客户5 : x为”-2”, 计算出x转换成整数后, +1的结果

...

import java.util.function.Function;
public class FunctionInterfaceUse {
    public static void main(String[] args) {
        // 1)客户1 : y为x的2倍
        Function<Integer,Integer> fun = x -> 2*x;
        System.out.println(testFunction(5,fun));// 10
        // 2)客户2 : y与x相等
        Function<Integer,Integer> fun2 = x ->x;
        System.out.println(testFunction(666,fun2));// 666
        // 3)客户3 : y为x的平方
        Function<Integer,Integer> fun3 = x -> x*x;
        System.out.println(testFunction(10,fun3));// 100

        //4)客户4 : x为”6” , 计算出x转换成整数后, 2倍结果
        Function<String,Integer> fun4 = x -> Integer.parseInt(x);
        System.out.println(testFunction2("6",fun4,fun));// 12

        //5)客户5 : x为”-2”, 计算出x转换成整数后, +1的结果
        Function<Integer,Integer> fun5 = x -> x+1;
        System.out.println(testFunction2("-2",fun4,fun5));// -1
    }
   /* 案例1 : 定义一个方法功能, 根据整数x,计算出对应整数y, x数据由客户给出, y数据的计算方式根据客户要求决定
    1)客户1 : y为x的2倍
    2)客户2 : y与x相等
    3)客户3 : y为x的平方
    4)...

    参数列表分析:
    1. 参数1: 提供int x
    2. 参数2: 提供Function<Integer,Integer>, 就是为了提供唯一抽象方法 Integer apply(Integer i)
    */
    public static int testFunction(int x, Function<Integer,Integer> fun){
        return fun.apply(x);
    }

    /*案例2 : 定义一个方法功能, 根据字符串x,计算出对应整数y, x数据由客户给出,
    y数据的计算方式根据客户要求决定
    1)客户4 : x为”6” , 计算出x转换成整数后, 2倍结果
    2)客户5 : x为”-2”, 计算出x转换成整数后, +1的结果
    ...

    参数列表分析:
    1. 参数1 : 提供String x
    2. 参数2: 将一个String类型转换成Integer类型,Function<String,Integer>, 为了传递Integer apply(String)
    3. 参数3: 将2计算结果,整数的x, 计算出一个整数结果y, Function<Integer,Integer>, 为了传递
       Integer apply(Integer)
    */

    public static int testFunction2(String x,Function<String,Integer> fun1,
                                    Function<Integer,Integer> fun2){
       /*// 将x由制字符串转成成Integer
         Integer i = fun1.apply(x);
         // 将Integer的结果计算出需要的y值
         Integer i2 = fun2.apply(i);
         return i2;*/

        // andThen方法表示将fun1的apply结果作为fun2函数式接口中方法的参数, andThen方法的返回值结果
        // 就是fun2的结果
        // 注意: 使用andThen方法功能时候,需要注意, fun1的结果需要与fun2参数类型保持一致
        //  return fun1.andThen(fun2).apply(x);
         return fun2.apply(fun1.apply(x));
    }
}

 

(二) 断言型接口

1、Predicate<T>: 断言型接口

2、抽象方法:boolean test(T t) 判断给定的数据是否符合某个条件

3、作用:

       如果需要定义一个函数,接收一个数据,判断数据是否合法,返回一个boolean结果,就可以使用断言型接口,以前我们只能传递过滤好的数据,而现在既可以传递原始数据,也可以传递过滤的条件

4、其他功能:

       Predicate  and(Predicate pre):在调用者条件判断之后,再由参数条件判断,返回两个条件都满足的判断对象 &&

       Predicate  or(Predicate pre):返回两个条件任意一个满足的判断对象  ||

Predicate negate():取判断结果的反向结果  !

 

案例1 :

  定义出一个方法, 需要客户提供一个容器ArrayList<Integer>, 根据客户的需求, 将容器中符合条件的数据筛选出来, 将筛选出的数据放置在新容器中返回给客户

1) 客户1 : 要求容器中的所有数, 都能被2整除

2) 客户2 : 要求所有的数据都不大于100

3) 客户3 : 要求所有数据都小于100, 并且都是奇数

4) 客户4 : 要求所有数据或者小于100, 或者是偶数

5) ...

 

import java.util.ArrayList;
import java.util.function.Predicate;
public class PredicateInterfaceUse {
    public static void main(String[] args) {
        ArrayList<Integer> list = new ArrayList<>();
        list.add(12);
        list.add(-6);
        list.add(101);
        list.add(188);
        list.add(9);
        list.add(99);
        // 1)客户1 : 要求容器中的所有数, 都能被2整除
        Predicate<Integer> pre1 = x -> x % 2 == 0;
        System.out.println(testPredicate(list,pre1));// [12, -6, 188]
        // 2)客户2 : 要求所有的数据都不大于100
        Predicate<Integer> pre2 = x -> x <= 100;
        System.out.println(testPredicate(list,pre2));// [12, -6, 9, 99]

        // 3)客户3 : 要求所有数据都小于100, 并且都是奇数
        // 使用Predicate接口中的默认方法,negate(), 表示获取的结果是pre1数据结果的取反
        Predicate<Integer> pre3 = pre1.negate();
        // pre2.and(pre3) : 将pre2的规则与pre3规则做&&运算
        System.out.println(testPredicate(list,pre2.and(pre3)));// [9, 99]

        // 4)客户4 : 要求所有数据或者小于100, 或者是偶数
        System.out.println(testPredicate(list,pre2.or(pre1)));// [12, -6, 188, 9, 99]
    }

    /*案例1 :
    定义出一个方法, 需要客户提供一个容器ArrayList<Integer>, 根据客户的需求,
    将容器中符合条件的数据筛选出来, 将筛选出的数据放置在新容器中返回给客户
    1)客户1 : 要求容器中的所有数, 都能被2整除
    2)客户2 : 要求所有的数据都不大于100
    3)客户3 : 要求所有数据都小于100, 并且都是奇数
    4)客户4 : 要求所有数据或者小于100, 或者是偶数
    5)...

    分析方法参数列表:
    1. 第一个参数: 需要客户提供ArrayList<Integer> 原始容器
    2. 第二个参数: 需要一个对于集合中的数据进行验证的规则, 因此提供Predicate<Integer>,实际上为了
       传递boolean test(Integer)
    */
    public static ArrayList<Integer> testPredicate(ArrayList<Integer> list,
                                                   Predicate<Integer> pre){
         ArrayList<Integer> result = new ArrayList<>();
         // 1. 遍历提供的list集合,获取出每一个元素
         for(Integer i : list){
            if(pre.test(i)){
                result.add(i);
            }
         }
         return result;
    }
}

 

一. 方法引用

1、写一个函数式接口时,方法的实现(lambda体),已经被某个其他的对象实现了,就不需要在Lambda体中,再次实现一遍,而可以直接使用那个已经定义好的方法。

2、格式:

       函数式接口 名称 = 对象名 :: 方法名称;

       函数式接口 名称 = 类名 :: 静态方法名;

3、作用:

       把已经实现的方法,作为一个数据,作为实现类对象,赋值给某个函数式接口的引用

       可以把这个引用当做方法的返回值,也可以作为方法的实际参数进行传递

4、本质:

       可以把任意一个方法,作为函数式接口的一个实现类对象

public class 方法引用 {
    public static void main(String[] args) {
        // 1. 使用lambda表达式实现函数式接口Inter
        Inter inet = x -> {
            for(int i = 1; i<= x; i++){
                System.out.println(i);
            }
        };

        inet.print(5);

        System.out.println("---------------------");

        // 2. 因为lambda表达式要实现的lambda体与PrintTest1类中的print方法一样
        // 因此可以借用一下PrintTest1类中的print方法, 这就叫这方法引用(使用PrintTest1类中的print方法代替lambda表达式)
        // 函数式接口 接口名 = 对象::方法名;
        Inter inet2 = new PrintTest1() :: print;
        inet2.print(8);

        System.out.println("+++++++++++++++++++++++");

        // 3. 因为lambda表达式要实现的lambda体与PrintTest2中静态方法p一样
        // 因此利用方法引用,借用PrintTest2中静态方法p方法道题lambda表达式
        // 函数式接口 接口名 = 类名::方法名;
        Inter inet3 = PrintTest2 :: p;
        inet3.print(6);

        // 4.
        Inter inet4 = x -> System.out.println(x);
        inet4.print(99);

       // System.out: 结果是一个PrintStream类型的对象, println就是来自于PrintStream中
        Inter inet5 = System.out :: println;
    }
}

@FunctionalInterface
interface Inter{
    public abstract void print(int n);
}

class PrintTest1{
    public void print(int n){
        for(int i = 1; i<= n; i++){
            System.out.println(i);
        }
    }
}

class PrintTest2{
    public static void p(int x){
        for(int i = 1; i<= x; i++){
            System.out.println(i + "--");
        }
    }
}

 

二. 方法引用

1、写一个函数式接口时,方法的实现(lambda体),已经被某个其他的对象实现了,就不需要在Lambda体中,再次实现一遍,而可以直接使用那个已经定义好的方法。

2、格式:

       函数式接口 名称 = 对象名 :: 方法名称;

       函数式接口 名称 = 类名 :: 静态方法名;

3、作用:

       把已经实现的方法,作为一个数据,作为实现类对象,赋值给某个函数式接口的引用

       可以把这个引用当做方法的返回值,也可以作为方法的实际参数进行传递

4、本质:

       可以把任意一个方法,作为函数式接口的一个实现类对象

public class 方法引用 {
    public static void main(String[] args) {
        // 1. 使用lambda表达式实现函数式接口Inter
        Inter inet = x -> {
            for(int i = 1; i<= x; i++){
                System.out.println(i);
            }
        };

        inet.print(5);

        System.out.println("---------------------");

        // 2. 因为lambda表达式要实现的lambda体与PrintTest1类中的print方法一样
        // 因此可以借用一下PrintTest1类中的print方法, 这就叫这方法引用(使用PrintTest1类中的print方法代替lambda表达式)
        // 函数式接口 接口名 = 对象::方法名;
        Inter inet2 = new PrintTest1() :: print;
        inet2.print(8);

        System.out.println("+++++++++++++++++++++++");

        // 3. 因为lambda表达式要实现的lambda体与PrintTest2中静态方法p一样
        // 因此利用方法引用,借用PrintTest2中静态方法p方法道题lambda表达式
        // 函数式接口 接口名 = 类名::方法名;
        Inter inet3 = PrintTest2 :: p;
        inet3.print(6);

        // 4.
        Inter inet4 = x -> System.out.println(x);
        inet4.print(99);

       // System.out: 结果是一个PrintStream类型的对象, println就是来自于PrintStream中
        Inter inet5 = System.out :: println;
    }
}

@FunctionalInterface
interface Inter{
    public abstract void print(int n);
}

class PrintTest1{
    public void print(int n){
        for(int i = 1; i<= n; i++){
            System.out.println(i);
        }
    }
}

class PrintTest2{
    public static void p(int x){
        for(int i = 1; i<= x; i++){
            System.out.println(i + "--");
        }
    }
}

 

这篇关于JavaSE基础day27 函数型接口Funtion、断言型接口Predicate、方法引用的文章就介绍到这儿,希望我们推荐的文章对大家有所帮助,也希望大家多多支持为之网!