函数式接口概述

函数式接口:

有且仅有一个抽象方法的接口

Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于Lambda使用的接口
只要确定了该接口有且仅有一个抽象方法,那么Lambda表单式就可以推导
Lambda表达式: 使用Lambda表达式的前提是该类是一个接口,并且有且仅有一个抽象方法
函数式接口 -> Lambda表达式

函数式接口的对象:

1.可以用作方法传递

2.同样可以是局部变量

代码实例:
public class Test {
public static void main(String[] args) {
// 函数式接口被当做局部变量的时候,可以直接赋值Lambda表达式
InterfaceTest it =()-> System.out.println(“函数式接口”);
it.show(); } }

检验接口是否为函数式接口

函数式接口注释:

@FunctionalInterface

代码实例:
// 定义一个有且只有一个方法的函数式接口,为了更好的区别函数式接口和其他接口的区别
// Java提供了@FunctionInterface注解标记函数式接口
_@FunctionalInterface
_public interface InterfaceTest { void show();}

Tips:

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

函数式接口作为方法的参数

需求:

  • 定义一个类(RunnableDemo),在类中提供两个方法
    • 一个是:startThread(Runnable r)方法参数Runnable是一个函数是借口
    • 一个方法是主方法,在主方法中调用startThread方法
  • 如果方法的参数是一个函数式接口,我们可以将Lambda表达式作为参数直接传递
    • startThread)(()->System.out.println(Thread.currentThread().getName()+”启动”));
  • 通俗理解就是如果知道调用的接口是函数式接口,可以不用刻意去创建对象实现,直接调用Lambda实现即可
  • 函数接口是可以作为方法的参数直接用Lambda实现的,并不只是这一种匿名实现

public class RunnableDemo {
public static void main(String[] args) {
startThread(()
-> System.out.println(Thread.currentThread().getName() + “ Lambda启动”));
// 匿名内部类调用方法
startThread(new Runnable() {
@Override
_public void run() {
System.out.println(Thread.currentThread().getName() + “ 匿名内部类启动”); } }); }

private static void startThread(Runnable _r
) {
// Runnable是只有一个抽象方法的接口是函数式接口
/ Thread t = new Thread(r);
t.start();
/
// 使用匿名类
new Thread(r).start(); }

函数式接口作为方法的返回值

需求:

  • 定义一个类(ComparatorDemo),在类中提供两个方法
    • 一个是方法是:Comparator getComparator()
    • 定义返回值是Compartor, 而方法返回值Comparator是一个函数式接口
    • 一个方法是主方法,在主方法中调用getComparator方法
  • 如果方法的返回值是一个函数式接口,我们可以将Lambda表达式作为结果返回
    • private Comparator getComparator(){ return(s1,s2)->s1.length() -s2.length();}

public class ComparatorDemo {
public static void main(String[] args) {
// 构造使用场景,定义集合存储字符串
ArrayList<String> al = new ArrayList<>();
al.add(“e”);
al.add(“aaaaa”);
al.add(“ccc”);
al.add(“dd”);
al.add(“bbbb”);
System.out.println(“排序前: “ + al);
// 使用Collections集合工具类的sort()自然排序方法排序
Collections.sort(al);
// 自然排序后: [aaaaa, bbbb, ccc, dd, e]
// 使用Collections集合工具类的sort()中带比较器接口的方法
// getComparator()定义比较器的方法中是比较长度
Collections.sort(al,getComparator());
System.out.println(“自然排序后: “ + al);
// 自然排序后: [e, dd, ccc, bbbb, aaaaa] **}

  1. **private static Comparator**<**String**> **getComparator**() {<br /> **// Comparable是一个函数是接口<br /> // 只有一个抽象方法 public int compareTo(T o);<br /> // 匿名内部类实现<br /> Comparator**<**String**> **cp = new Comparator**<**String**>() {<br /> **_@Override<br /> _public int compare**(**String _s1_, String _s2_**) {<br /> **return _s1_.length**() **- _s2_.length**()**; **} }**;<br /> return cp;<br /> // 返回cp这个对象就是返回匿名内部类,可以直接返回<br /> return new Comparator<String>(){<br /> _@Override<br /> _public int compare(String _s1_, String _s2_) {<br /> return _s1_.length() - _s2_.length(); } };<br /> // Lambda表达式实现比较比较器函数是接口比较长度<br /> return **(**String _s1 _,String _s2_**)**->**{ **return _s1_.length**() **- _s2_.length**()**; **}**;<br /> // 简化Lambda表达式<br /> return **(**_s1_, _s2_**) **-> _s1_.length**() **- _s2_.length**()**;<br /> // 简化使用方法饮用String比较字符串长度String::length<br /> return Comparator.**comparingInt(**String::length**)**; **} }**

常用的函数式接口

  1. - **Supplier接口**
  2. - **Consumer接口**
  3. - **Predicate接口**
  4. - **Function接口**


函数式接口之Supplier接口

Supplier: 包含一个无参的方法

  • T get(): 获得结果
  • 该方法不需要参数,这是一个功能界面,可以按照某种实现逻辑(由Lambda表达式实现)返回一个数据
  • Supplier接口也被称为生产型接口,就是我们指定了接口的泛型是什么类型,那么Supplier这个T是什么类型,该接口的get()方法就是什么类型的数据

image.png

函数式接口之Consumer接口

Consumer: 包含两个方法

  • void accept(T t) 对给定的参数执行此操作
  • default Consumer andThen(Consumer<? super T> after)
    • 返回一个组合的 Consumer ,按顺序执行该操作,然后执行 after操
  • Consumer接口也被称为消费性接口。它使用数据的类型由泛型指定

image.png

函数式接口之Predicate接口

Predicate: 常用的四个方法

  • boolean test(T t) 在给定的参数上评估这个谓词。
  • default Predicate negate() 返回表示此谓词的逻辑否定的谓词。
  • default Predicate and(Predicate<? super T> other)
    • 返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑AND。
    • 有false就是false
  • default Predicate or(Predicate<? super T> other)
    • 返回一个组合的谓词,表示该谓词与另一个谓词的短路逻辑或。
    • 有true则true,
  • Predicate接口通常用于判断参数是否满足指定的条件

image.png
image.png
public class Test {
public static void main(String[] args) {
String[] strArray = {“王五,22”, “张曼玉,34”, “林青霞,21”, “李四,34”, “张三,33”};
ArrayList<String> al = usePredicate(strArray, s -> s.split(“,”)[0].length() > 2,
s -> Integer.parseInt(s.split(“,”)[1]) > 33);
for (String s : al) {
System.out.println(s); **} }

  1. **private static ArrayList**<**String**> **usePredicate**(**String**[] **_str_, Predicate**<**String**> **_p1_, Predicate**<**String**> **_p2_**) {
  2. **ArrayList**<**String**> **al = new ArrayList**<>()**;<br /> for **(**String s : _str_**) {<br /> **// 使用Predicate函数是借口中的and()和test()方法判断<br /> if **(**_p1_.and**(**_p2_**)**.test**(**s**)){<br /> **al.add**(**s**)**; **} }<br /> **return al; **} }**

函数式接口之Function接口

Function 常用的两个方法:

  • R apply(T t) 将此函数应用于给定的参数。
  • default Function andThen(Function<? super R,? extends V> after)
    • 返回一个组合函数,首先将该函数应用于其输入,然后将 after函数应用于结果。
  • Function接口通常用于对参数进行处理, 转换然后返回一个新的值

image.pngimage.png
public class Test {
public static void main(String[] args) {
String 李畅 =”李畅,26”;
useFunction(李畅, s -> s.split(“,”)[1], Integer::parseInt,
integer -> integer+70); **}

private static void useFunction(String s, Function<String,String>f1,Function<String,Integer> f2,Function<Integer,Integer> f3) {
int i = f1.andThen(f2).andThen(f3).apply(s);
System.out.println
(i); } }