函数式接口

1.1函数式接口概述
函数式接口:有且仅有一个抽象方法的接口
Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口
只有确保接口中有且仅有一个抽象方法, Java中的L ambda才能顺利地进行推导

如何检测一个接口是不是函数式接口呢?
@Functionallnterface放在接口定义的上方:

如果接口是函数式接口,编译通过;如果不是,编译失败


注意
●我们自己定义 函数式接口的时候,@Functionallnterface是可选的, 就算我不写这个注解,只要保证满足函数式接口定
义的条件,也照样是函数式接口。但是,建议加上该注解



1.2函数式接口作为方法的参数
需求
● 定义一个类(RunnableDemo),在类中提供两个方法
一个方法是: startThread(Runnable r)方法参数Runnable是一 个函数式接口
一个方法是主方法,在主方法中调用startThread方法
如果方法的参数是一个函数式接口, 我们可以使用 ambda表达式作为参数传递
●startThread(0 -> System.out.println(Thread.currentThread0.getName0 + "线程启动了));

package com.Test01;
/*
    定义一个类(RunnableDemo),在类中提供两个方法
    一个方法是: startThread(Runnable r) 方法参数Runnable是一 个函数式接口
    一个方法是主方法,在主方法中调用startThread方法

 */

public class RunnableDemo {
    public static void main(String[] args) {
        //在主方法中调用startThread方法

        //采用匿名内部类的方式
        startThread(new Runnable() {
            @Override
            public void run() {
                System.out.println(Thread.currentThread().getName() + "线程启动了");
                

            }
        });
      startThread (() -> System.out.println(Thread.currentThread().getName() + "线程启动了"));
  } private static void startThread(Runnable r) { // Thread t = new Thread(r); // t.start(); new Thread(r).start(); } }

1.3函数式接口作为方法的返回值
需求●定义一个类(ComparatorDemo), 在类中提供两个方法
一个方法是: Comparator <String> getComparator()方法返回值C omparator是一个函数式接口
一个方法是主方法,在主方法中调用getComparator方法


如果方法的返回值是一个函数式接口,我们可以使用L ambda表达式作为结果返回
●private static Comparator <String> getComparator({
return (s1, s2) -> s1.length( - s2.length0;
}

package com.Test01;

import java.util.ArrayList;
import java.util.Collections;
import java.util.Comparator;

public class CommparatorDemo {
    public static void main(String[] args) {
        //构造使用场景

        //定义集合 存储字符串元素
        ArrayList<String> array = new ArrayList<String>();
        array.add("cccc");
        array.add("aaa");
        array.add("dd");
        array.add("b");
        System.out.println("排序前:" + array);
        Collections.sort(array, getComparator());
        System.out.println("排序后:" + array);


    }

    public static Comparator<String> getComparator() {
        //返回该接口的实现类对象
        //首先采用匿名内部类的方式
//        Comparator<String> comp = new Comparator<String>() {
//            @Override
//            public int compare(String s1, String s2) {
//                return s1.length()-s2.length();
//            }
//        };
//        return comp;
//        return new Comparator<String>() {
////            @Override
////            public int compare(String s1, String s2) {
////                return s1.length() - s2.length();
////            }
////        };
//        return (String s1,String s2) ->{
//            return s1.length()-s2.length();
//        };
        return (s1, s2) -> s1.length() - s2.length();

    }
}

 


常用的4个函数式接口

Java 8在java.util.function包下预定义了大量的函数式接口供我们使用
我们重点来学习下面的4个接口
●Supplier接口
●Consumer接口
●Predicate接口、
●Function接口

 


 

1,Supplier接口

 

@FunctionalInterface
public interface Supplier<T>

 

代表结果供应商。

没有要求每次调用供应商时都会返回新的或不同的结果。

这是一个functional interface的功能方法是get()

 

 

package com.Test01;
/*
Supplier<T>:包含一个无参的方法
T get ():获得结果
该方法不需要参数,它会按照某种实现逻辑(由Lambda表达式实现)返回一个数据
Supplier<T>接口也被称为生产型接口,如果我们指定了接口的泛型是什么类型,那么接口中的get方法就会生产什么类型的数据供使用

 */

import java.util.function.Supplier;

public class SupplierDemo {
    public static void main(String[] args) {
//        String s = getString(() -> {
//            return "林青霞";
//        });
        String s = getString(() -> "林青霞");
        System.out.println(s);

    }
    private static String getString(Supplier<String> sup) {
        return sup.get();
    }
}

 

 

 

 

 

 

package com.Test01;

import java.util.function.Supplier;

public class SupplierTest {
    public static void main(String[] args) {
        //定义一个数组
        int[] arr = {15, 20, 3, 65, 45, 6};

        int x = getMax(() -> {
            int Max = arr[0];
            for (int i = 0; i < arr.length; i++) {
                if (Max < arr[i]) {
                    Max = arr[i];
                }

            }
            return Max;
        });
        System.out.println(x);  
    }

    private static int getMax(Supplier<Integer> sup) {
        return sup.get();
    }
}

 


,2,Consumer接口

 

@FunctionalInterface
public interface Consumer<T>

 

表示接受单个输入参数并且不返回结果的操作

 

1.6 Consumer接口
  Consumer<T>:包含两个方法
void accept(T t): 对给定的参数执行此操作
default Consumer <T> andThen(Consumer after):返回一个组合的Consumer,依次执行此操作,然后执行after操作
●Consumer<T>接口也被称为消费型接口,它消费的数据的数据类型由泛型指定

 

 

 

package com.Test01;
/*
Consumer<T>:包含两个方法
void accept (T t): 对给定的参数执行此操作
default Consumer<T> andThen (Consumer after): 返回一个组合的Consumer, 依次执行此操作,然后执行after操作
Consumer<T>接口也被称为消费型接口,它消费的数据的数据类型由泛型指定
/

 */

import java.util.function.Consumer;

public class ConsumerDemo {
    public static void main(String[] args) {
//        Lamada表达式
//        OperatorString("林青霞",(s) -> {
//            System.out.println(s);
//        });

//        OperatorString("林青霞", (s) -> System.out.println(s));
        //方法引用
        OperatorString("林青霞", System.out::println);
    }

    //定义一个方法,消费一个字符串数据
    private static void OperatorString(String name, Consumer<String> con) {
        con.accept(name);
    }
}

 

Consumer练习
String[] strArray = {"林青霞, 30",”张曼玉,35", ”王祖贤, 33"}; 字符串数组中有多条信息,请按照格式: "姓名: Xx,年龄: xX"的格式将信息打印出来 要求: 把打印姓名的动作作为第- -个Consumer接口的L ambdo实例 把打印年龄的动作作为第二个Consumer接口的L ambda实例 将两个Consumer接口按照顺序组合到一起使用




package com.Test01;
/**/

import java.util.function.Consumer;

public class ConsumerDemo02 {
    public static void main(String[] args) {
        String[] strArray = {"林青霞,30", "张曼玉,35", "王祖贤,33"};
        printString(strArray, (String str) -> {
            String name = str.split(",")[0];
            System.out.print("姓名:" + name);
        }, (String str) -> {
            int age = Integer.parseInt(str.split(",")[1]);
            System.out.println(",年龄:" + age);
        });

    }

    private static void printString(String[] strArray, Consumer<String> con1, Consumer<String> con2) {
        for (String s : strArray) {
            con1.andThen(con2).accept(s);
        }
    }
}

 

3, Predicate接口

@FunctionalInterface
public interface Predicate<T>
表示一个参数的谓词(布尔值函数)。


Predicate<T>:常用的四个方法
●boolean test(T t):对给定的参数进行判断(判断逻辑由L ambda表达式实现),返回一个布尔值
●default Predicate<T> negate():返回-一个逻辑的否定,对应逻辑非
●default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与
●default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或

-----------   - --  - - - - - - - - -- - - - - - - - - - - - - -- - -   -- - - - - - --

Predicate<T>接口通常用于判断参数是否满足指定的条件


 

●boolean test(T t):对给定的参数进行判断(判断逻辑由L ambda表达式实现),返回一个布尔值
●default Predicate<T> negate():返回-一个逻辑的否定,对应逻辑非

如下演示

package com.Test01;
/*
Predicate<T>:常用的四个方法
boolean test (T t):对给定的参数进行判断(判断逻辑由Lambda表达式实现),返回一个布尔值
default Predicate<T> negate (): 返回一个逻辑的否定,对应逻辑非
Predicate<T>接口通常用于判断参数是否满足指定的条件

 */


import java.util.function.Predicate;

public class PredicateDemo01 {
    public static void main(String[] args) {
//        boolean b = checkString("hello", (String s) -> {
//            return s.length() > 8;
//        });
        boolean b = checkString("hello", s -> s.length() > 8);
        System.out.println(b);

    }

    //判断给定的字符串是否满足要求
    private static boolean checkString(String s, Predicate<String> pre) {
//        return pre.test(s);
//        return !pre.test(s);//不是标准非
        return pre.negate().test(s);//接口提供的逻辑非的操作

    }
}

 

●default Predicate<T> and(Predicate other):返回一个组合判断,对应短路与
●default Predicate<T> or(Predicate other):返回一个组合判断,对应短路或

如下演示

package com.Test01;
/*
/*
Predicate<T>:
default Predicate<T> and (Predicate other): 返回一个组合判断,对应短路与
default Predicate<T> or (Predicate other): 返回-一个组合判断,对应短路或

 */

import java.util.function.Predicate;

public class PredicateDemo02 {
    public static void main(String[] args) {
        boolean b1 = checkString("hello", s -> s.length() > 8);
        //System.out.println(b1);
        boolean b2 = checkString("helloworld", s -> s.length() > 8);
        //System.out.println(b2);
        boolean b3 = checkStringandor("helloworld", s -> s.length() > 11, s -> s.length() < 15);
        System.out.println(b3);
    }

    //同一个字符串给出两个不同的判断条件,最后把这两个判断的结果做逻辑与运算的结果作为最终的结果
    private static boolean checkStringandor(String s, Predicate<String> pre1, Predicate<String> pre2) {
//        boolean b1 = pre1.test(s);
////        boolean b2 = pre2.test(s);
////        boolean b = b1 || b2;
////        return b;
        return pre1.or(pre2).test(s);//return pre1.and(pre2).test(s);
    }

    private static boolean checkString(String s, Predicate<String> pre) {
        //判定给定的字符串是否满足要求
        return pre.test(s);
//

    }

}

 Predicate练习
String[ strArray= {"林青霞30", "柳岩,34", "张曼玉,35",“貂蝉,31", "王祖贤,33"};
●字符串数组中有多条信息, 请通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,并遍历ArrayList集合
●同时满足如下要求:姓名长度大于2;年龄大于33

分析
有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断
必须同时满足两个条件,所以可以使用and方法连接两个判断条件

package com.Test01;
/*
String[] strArray = {"林青霞,30”,“柳岩,34", "张曼玉,35", "貂蝉,31","王祖贤,33"};
字符串数组中有多条信息,请通过Predicate接口的拼装将符合要求的字符串筛选到集合Arraylist中,并遍历Arraylist集合
要求:同时满足如下要求
1:姓名长度大于2
2:年龄大于33
分析:
1:有两个判断条件,所以需要使用两个Predicate接口,对条件进行判断
2:必须同时满足两个条件,所以可以使用and方法连接两个判断条件

 */

import java.util.ArrayList;
import java.util.function.Predicate;

public class PredicateTest {
    public static void main(String[] args) {
        String[] strArray = {"林青霞,30", "柳岩,34", "张曼玉,35", "貂蝉,31", "王祖贤,33"};
        ArrayList<String> stringArrayList = myfilter(strArray, s -> s.split(",")[0].length() > 2, s -> Integer.parseInt(s.split(",")[1]) > 33);
        for (String s : stringArrayList) {
            System.out.println(s);
        }
    }

    //    请通过Predicate接口的拼装将符合要求的字符串筛选到集合ArrayList中,
    private static ArrayList<String> myfilter(String[] arr, Predicate<String> pre1, Predicate<String> pre2) {
        //定义一个集合
        ArrayList<String> array = new ArrayList<String>();
        for (String s : arr) {
            String name = s.split(",")[0];
            int age = Integer.parseInt(s.split(",")[1]);
            if (pre1.and(pre2).test(s)) {
                array.add(s);
            }
        }

        return array;

    }

}

4, Function接口

@FunctionalInterface
public interface Function<T,R>
表示接受一个参数并产生结果的函数


Function<T,R>:常用的两个方法
R apply(Tt):将此函数应用于给定的参数
default <V> Function andThen(Function after):返回-个组合函数,首先将该函数应用于输入,然后将after函数应用于结果
Function<T,R>接口通常用于对参数进行处理,转换(处理逻辑由Lambda表达式实现),然后返回一个新的值

package com.Test01;
/*
Function<T,R>:常用的两个方法
R apply (T t):将此函数应用于给定的参数
default <V> Function andThen (Function after): 返回一个组合函数,首先将该函数应用于输入,然后将ofter函数应用于结果
Function<T, R>接口通常用于对参数进行处理,转换(处理逻辑由L ambda表达式实现),然后返回一一个新的值

 */

import java.util.function.Function;

public class FunctionDemo {

    public static void main(String[] args) {
//        Convert("100", (String s) -> {
//            return Integer.parseInt(s);
//        });
        Convert("100", s -> Integer.parseInt(s));
        Convert("100", Integer::parseInt);
        Convert(100, i-> String.valueOf(i+566));
        Convert("300",s->Integer.parseInt(s),i->String.valueOf(i+300));

    }

    //定义一个方法,把一个字符串转换int类型,在控制台输出
    private static void Convert(String s, Function<String, Integer> fun) {
//        Integer i = fun.apply(s);
        int i = fun.apply(s);
        System.out.println(i);
    }


    //定义一个方法,把一个int类型的数据加上一个整数之后,转为字符串在控制台输出
    private static void Convert(int i, Function<Integer, String> fun) {
        String s = fun.apply(i);
        System.out.println(s);
    }

    //定义一个方法,把一个字符串转换int类型,把int类型的数据加上一一个整数之后,
    // 转为字符串在控制台输出
    private static void Convert(String s,Function<String,Integer> fun1,Function<Integer,String> fun2) {
//        Integer i = fun1.apply(s);
//        String s1 = fun2.apply(i);
//        System.out.println(s1);
        String s1 = fun1.andThen(fun2).apply(s);
        System.out.println(s1);
    }


}

练习

package com.Test01;
/*
●Strings = "林青霞30";
●请按照我指定的要求进行操作:
1:将字符串截取得到数字年龄部分string
2:将上一步的年龄字符串转换成为int类型的数据int
3:将上一步的int数据加70,得到个int结果,在控制台输出
●请通过Function接口来实现函数拼接
*/

import java.util.function.Function;

public class FunctionDemo02 {
    public static void main(String[] args) {
        Convert("林青霞30",s->  Integer.parseInt(s.substring(3,5))+70);  //也可以按照题目的要求一步一步来

    }

    private static void Convert(String s, Function<String, Integer> fun) {
        Integer i = fun.apply(s);
        System.out.println(i);
    }


}

 

 

posted @ 2019-09-02 21:26  水果、、  阅读(874)  评论(0编辑  收藏  举报