专栏首页Java深度编程Java 8新特性 -- 函数式接口

Java 8新特性 -- 函数式接口

JDK1.8提供一种特殊的接口 -- 函数式接口(Functional Interface),它与普通接口相比,就是比普通的接口多了一个方法。 函数式接口可以被隐式转换为lambda表达式。函数式接口现有的函数可以友好地支持 lambda。

其实早在JDK 1.8之前就已经有了一些函数式接口,如下:

  • java.lang.Runnable
  • java.util.concurrent.Callable
  • java.security.PrivilegedAction
  • java.util.Comparator
  • java.io.FileFilter
  • java.nio.file.PathMatcher
  • java.lang.reflect.InvocationHandler
  • java.beans.PropertyChangeListener 等

JDK 1.8 版本新增加的函数接口:

  • java.util.function

java.util.function 可以用来支持 Java的 函数式编程,该包中的函数式接口有:

序号

接口 & 描述

1

BiConsumer<T,U>代表了一个接受两个输入参数的操作,并且不返回任何结果

2

BiFunction<T,U,R>代表了一个接受两个输入参数的方法,并且返回一个结果

3

BinaryOperator<T>代表了一个作用于于两个同类型操作符的操作,并且返回了操作符同类型的结果

4

BiPredicate<T,U>代表了一个两个参数的boolean值方法

5

BooleanSupplier代表了boolean值结果的提供方

6

Consumer<T>代表了接受一个输入参数并且无返回的操作

7

DoubleBinaryOperator代表了作用于两个double值操作符的操作,并且返回了一个double值的结果。

8

DoubleConsumer代表一个接受double值参数的操作,并且不返回结果。

9

DoubleFunction<R>代表接受一个double值参数的方法,并且返回结果

10

DoublePredicate代表一个拥有double值参数的boolean值方法

11

DoubleSupplier代表一个double值结构的提供方

12

DoubleToIntFunction接受一个double类型输入,返回一个int类型结果。

13

DoubleToLongFunction接受一个double类型输入,返回一个long类型结果

14

DoubleUnaryOperator接受一个参数同为类型double,返回值类型也为double 。

15

Function<T,R> 接受一个输入参数,返回一个结果。

16

IntBinaryOperator接受两个参数同为类型int,返回值类型也为int 。

17

IntConsumer接受一个int类型的输入参数,无返回值 。

18

IntFunction<R>接受一个int类型输入参数,返回一个结果 。

19

IntPredicate:接受一个int输入参数,返回一个布尔值的结果。

20

IntSupplier无参数,返回一个int类型结果。

21

IntToDoubleFunction接受一个int类型输入,返回一个double类型结果 。

22

IntToLongFunction接受一个int类型输入,返回一个long类型结果。

23

IntUnaryOperator接受一个参数同为类型int,返回值类型也为int 。

24

LongBinaryOperator接受两个参数同为类型long,返回值类型也为long。

25

LongConsumer接受一个long类型的输入参数,无返回值。

26

LongFunction<R>接受一个long类型输入参数,返回一个结果。

函数式接口实例

Predicate <T> 接口是一个函数式接口,它接受一个输入参数 T,返回一个布尔值结果。

该接口包含多种默认方法来将Predicate组合成其他复杂的逻辑(比如:与,或,非)。

该接口用于测试对象是 true 或 false。

我们可以通过以下实例(Java8FunctionTest.java)来了解函数式接口 Predicate <T> 的使用:

package com.wenxue.jdk8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * @className: FunctionTest
 * @Description: TODO 测试java1.8的函数式接口
 * @version: v1.9.3
 * @author: GONGWENXUE
 * @date: 2019/12/11 15:39
 */
public class Java8FunctionTest {

    /**
     * @Author GONGWENXUE
     * @Description //TODO 测试 Predicate<T>函数式接口,传入一个参数n,返回一个boolean结果。
     * @version: v1.9.3
     * @Date 15:50 2019/12/11
     * @Param 
     * @return 
     **/
    public static void testFun(List<Integer> list, Predicate<Integer> predicate) {
        for(Integer n: list) {
            //当真正执行函数接口对象的test(n)时,才具体的传入了n的值。
            // 前面的表达式( n-> n%2 == 0)是函数式接口test方法的实现逻辑。
            if(predicate.test(n)) {
                System.out.println(n + " ");
            }
        }
    }

    public static void main(String[] args) {

        List<Integer> list = Arrays.asList(1, 2, 3, 4, 5, 6);
        System.out.println("输出所有偶数:");

        // Predicate<Integer> predicate1 = n -> 运算表达式(n%2==0)
        // n 是传递到 Predicate 接口的 test 方法的一个参数
        // n%2==0:是test方法的实现逻辑,这里是使用Lam表达式实现了对象的创建与抽象方法的实现
        // 调用方法传入n-> n%2 == 0时就已经实现了函数接口的对象与test方法的重写
        // 然后调用test方法,test方法的重写逻辑,从而返回ture或者false
        // n-> n%2 == 0: 标识函数式接口的test方法需要按照“参数值是偶数”时才返回true.
        testFun(list, n-> n%2 == 0 );//2,4,6

        System.out.println("输出大于 3 的所有数字:");
        testFun(list, n-> n > 3 );//4,5,6
    }

}

自定义函数式接口:

1.先编写函数式接口:

package com.wenxue.jdk8;

/**
 * @className: MyFunctionalInterface
 * @Description: TODO 自定义函数式接口
 * @version: v1.9.3
 * @author: GONGWENXUE
 * @date: 2019/12/11 21:14
 */
@FunctionalInterface
public interface MyFunctionalInterface<T> {
    
    Integer test(T t, T t2);
    //函数式接口有且只有一个抽象方法,写多个时@FunctionalInterface会报错
    //Integer test2(T t, T t2);
}

2.创建接口对象,实现抽象方法:

 MyFunctionalInterface<Integer> myFunctionalInterface =  (n,n2) -> n + n2;

3.调用函数接口方法:

package com.wenxue.jdk8;

import java.util.Arrays;
import java.util.List;
import java.util.function.Predicate;

/**
 * @className: FunctionTest
 * @Description: TODO 测试java1.8的函数式接口
 * @version: v1.9.3
 * @author: GONGWENXUE
 * @date: 2019/12/11 15:39
 */
public class Java8FunctionTest {

      public static void main(String[] args) {
        List<Integer> list = Arrays.asList(1, 2, 3);
    //创建函数式接口对象, 实现test方法的逻辑为将两个参数相加后返回
        MyFunctionalInterface<Integer> myFunctionalInterface =  (n,n2) -> n + n2;
        //调用函数式接口方法,执行运算逻辑
        testMyFunctionalInterface(list, myFunctionalInterface);
    }
  
    public static void testMyFunctionalInterface(List<Integer> list, MyFunctionalInterface<Integer> myFunctionalInterface) {
        for(Integer n: list) {
            Integer result = myFunctionalInterface.test(n,n);
            System.out.println(result);//2,4,6
        }
    }

}
函数接口与普通接口的区别:
函数接口只能有一个抽象方法(不包括继承或重写的Object的方法),普通接口可以有多个抽象方法。
@FunctionalInterface
public interface MyFunctionalInterface<T> {

    Integer test(T t, T t2);
    //函数式接口有且只有一个抽象方法,写多个会报错
    //Integer test2(T t, T t2);

    @Override//这个equals方法是从Object继承下来的,这里只是表示重写,所以不算多余的额外的抽象接口
    boolean equals(Object obj);
}

本文分享自微信公众号 - Java深度编程(JavaDeep),作者:龚文学

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2019-12-30

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • Java的浅克隆与深克隆

    “克隆”一词总会让我们想起与生物学相关的科技医学技术,说的就是将动物的细胞取到后进行人工培育,从而培育出一个一模一样的动物(当然也包括人)。在编程界中...

    Java深度编程
  • Java1.8新特性--方法的引用

    上面的car2::repair为什么报错?点开forEach源码你会发现它需要的参数是:Consumer<? super T> ,而对象::空参方法得到的返回值...

    Java深度编程
  • spring的定时任务,超级简单好用

    @EnableScheduling 注解的作用是发现注解@Scheduled的任务并后台执行。@Scheduled用于标注这个方法是一个定时任务的方法cro...

    Java深度编程
  • 第二期-wepy安装

    简单介绍:wepy是一个微信小程序框架,支持模块化开发,开发风格类似Vue.js。可搭配redux使用,能同时打包出web和小程序。

    小团子
  • 通杀绝⼤多数交易平台的Tradingview Dom XSS漏洞分析

    本文主要是分析慢雾安全团队《⼀个通杀绝⼤多数交易平台的 XSS 0day 漏洞》.aspx),根据慢雾区匿名情报,通用 K 线展示 JS 库 TradingVi...

    FB客服
  • ASP.NET Core - 在ActionFilter中使用依赖注入

    当我们的ActionFilter需要使用某个Service的时候,我们一般会通过构造函数注入。 演示一下,首先自定义一个ActionFilter,通过构造...

    kklldog
  • Android中极简的js与java的交互库-SimpleJavaJsBridge

    最近接触android中js与java交互的东西很多,当然它们之间的交互方式有几种,但是我觉得这几种交互方式都存在一定的不足,这是我决定编写SimpleJava...

    用户2802329
  • 网页开发之目前流行的五大浏览器内核介绍

    浏览器的内核是分为两个部分的,一是渲染引擎,另一个是JS引擎。现在JS引擎比较独立,内核更加倾向于说渲染引擎。

    用户1289394
  • bitfinex币 接口翻译整理

    code_horse
  • 【图像分割模型】多分辨率特征融合—RefineNet

    这是专栏《图像分割模型》的第8篇文章。在这里,我们将共同探索解决分割问题的主流网络结构和设计思想。

    用户1508658

扫码关注云+社区

领取腾讯云代金券