函数式接口

1. 函数式接口

1.1 概述

如果说一个接口内有且只有一个方法,而且该方法是一个缺省属性为public abstract方法,该接口可以称之为是一个函数式接口。
   自定义函数式接口,还有系统中提供的函数式接口
   Comparator< T > Runnable

可以直接理解JDK1.8的新特征,Lambda表达式来使用。

Lambda表达式对比匿名内部类使用
   1. 简化了代码结构
   2. 节约了内存资源
   3. 让程序员更加关注,我要做什么,而不是为了做什么需要完成什么

1.2 @FunctionalInterface 使用

类似于
   @Override
   开启代码重写格式严格检查

/*** 使用@FunctionalInterface检查函数式接口格式问题* 要求当前接口中有且只有一个缺省属性为public abstract的方法**/
@FunctionalInterface
public interface FunctionalType {void test();
}

只允许有一个缺省属性为public abstract的方法,除了重写父类的方法

1.3 使用自定义的函数式接口作为方法的参数使用

代码示例:

/*** 自定义函数式接口作为方法的参数演示** @author dididi*/
public class Demo1 {public static void main(String[] args) {/*使用匿名内部类来完成函数式接口的使用,但是这种方式有悖于函数式接口的目的LowuseFunctionalInterface(new FunctionalType() {@Overridepublic void test() {System.out.println("匿名内部类");}});int(*) (char **, int *)C语言中的函数指针如果是C语言中,这需要的参数是方法名*/useFunctionalInterface(() -> System.out.println("函数式接口 lambda表达式实现完成方法"));}/*** 使用一个函数式接口作为方法的参数** @param ft 函数式接口的实现类对象,或者说直接操作本质,直接传入Lambda表达式*/public static void useFunctionalInterface(FunctionalType ft) {ft.test();}
}

代码中使用函数式接口
   1. 让程序的目的性更强
   2. 提供复用,普适性的价值
   3. 节约资源

2 函数式编程思想

2.1 Lambda延迟执行

2.1.1 日志记录

日志是否保存会存在等级限制
   演示一个根据不同的等级来记录log日志
要求:
   等级 == HIGH 记录log日志,其他情况不记录
代码示例:

/*** 提供返回值为String类型方法的函数式接口**/
@FunctionalInterface
public interface LogMessage {/*** 函数式接口中方法内容,该方法的返回值是String类型** @return String类型返回值*/String returnLogMessage();
}
/*** 使用函数式接口完成Log日志记录问题**/
public class Demo2 {public static void main(String[] args) {String msg1 = "异常位置XXX,";String msg2 = "异常问题XXX,";String msg3 = "异常时间XXX";log(Level.LOWER, () -> {System.out.println("Lambda表达式执行!!!");return msg1 + msg2 + msg3;});}/*** 根据日志等级Level来确定是否需要记录日志** @param level Level枚举类型,有三个数据 HIGH MIDDLE LOWER* @param lm LogMessage函数式接口做方法的参数*/public static void log(Level level, LogMessage lm) {/*发现当Level等级为HIGH,执行对应的lm.returnLogMessage();Level等级不是HIGH不执行对应的方法。Lambda执行延迟问题不是Lambda效率执行慢,而是在执行之前多了一个判断是在判断之后才可以执行对应的代码。不执行代码字符串不会产生拼接导致的资源浪费问题,从而提高效率。*/if (Level.HIGH == level) {// 通过函数式接口获取调用对应的returnLogMessage()方法System.err.println(lm.returnLogMessage());}}

2.2 Lambda作为方法参数和返回值

代码示例:

/*** Runnable接口函数式接口使用,作为方法的参数**/
public class Demo3 {public static void main(String[] args) {// 匿名内部类来完成对应当前Runnable接口实现类对象使用,作为Thread构造方法参数// lownew Thread(new Runnable() {@Overridepublic void run() {System.out.println("线程代码");}}).start();// Lambda表达式直接作为方法的参数Thread thread = new Thread(() -> {System.out.println("线程执行需要时间");try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println("线程执行");}, "线程");thread.start();}
}

代码示例

3 Java中提供的常用函数式接口

3.1 JDK常用函数式接口概述

java.util.function包名 。提供了很多函数式接口
   规范了一些操作,提升了开发效率,更加专注于目的性!!!

Supplier 生产者, 返回一个指定类型的数据
   Consumer 消费者, 消耗一个指定类型的数据
   Predicate 判断调节,过滤使用
   Function<T,R> 类型转换,根据你指定的类型T, 转换成对应类型R

3.2 Supplier 生产者,返回一个指定的数据类型

java.util.function.Supplier
   有且只有一个方法
      T get();
      不需要参数,返回指定T类型数据
代码示例:

import com.qfedu.b_lambda.Level;import java.util.function.Supplier;/*** Supplier函数式接口演示**/
public class Demo1 {public static void main(String[] args) {String msg1 = "异常位置XXX,";String msg2 = "异常问题XXX,";String msg3 = "异常时间XXX";/*这里需要的是一个函数式接口,直接传入一个lambda表达式*/log(Level.HIGH, () -> {System.out.println("Lambda表达式执行!!!");return msg1 + msg2 + msg3;});/*Lambda表达式优化*/log(Level.HIGH, () -> msg1 + msg2 + msg3);}/*** 根据日志等级Level来确定是否需要记录日志** @param level Level枚举类型,有三个数据 HIGH MIDDLE LOWER* @param supplier Supplier函数式接口,利用T get() 完成提供数据操作*/public static void log(Level level, Supplier<String> supplier) {/*Supplier函数式接口利用get方法,提供对应的返回指定String类型数据的操作*/if (Level.HIGH == level) {// 通过函数式接口获取调用对应的returnLogMessage()方法System.err.println(supplier.get());}}
}

代码示例

3.3 Consumer消费者,处理数据

Consumer
   操作使用的方式是
   void accept(T t);
      根据接口指定的数据类型接收对应数据,进行处理和消费,对外没有任何的返回
      至于处理的过程,展示,处理,计算。。。
代码示例:

import java.util.function.Consumer;/*** 使用Consumer处理数据**/
public class Demo1 {public static void main(String[] args) {// 该方法需要的参数是一个String类型,同时使用Consumer接口处理数据// 因为Consumer接口是一个函数式接口,可以使用Lambda表达式testConsumer("宫保鸡丁,番茄牛腩,酱牛肉,黄焖鸡米饭", (str) -> {String[] split = str.split(",");for (String s : split) {System.out.println(s);}});}/*** 给予当前方法一个String类型,通过Consumer函数式接口中的accept方法完成对应* 字符串处理** @param str String类型字符串* @param consumer Consumer处理数据的函数式接口*/public static void testConsumer(String str, Consumer<String> consumer) {consumer.accept(str);}
}

andThen

代码示例:

import java.util.function.Consumer;/*** Consumer接口andThen使用* 需要两个Consumer接口,两个Consumer接口进行组合处理,对数据进行消费** andThen(Consumer<T> con)*      调用格式*          con1.andThen(con2).accept(T t);*          等价于一下操作*          con1.accept(t);*          con2.accept(t);**/
public class Demo2 {public static void main(String[] args) {/*该方法需要两个Consumer函数式接口,这里可以使用两个Lambda表达式操作*/testAndThen("郑州加油!!!中国加油!!!",(str) -> System.out.println(str),(str) -> System.err.println(str));}/*** 使用两个Consumer消费者方式处理str数据,首先是con1处理,再来con2处理** @param str  需要处理的String类型数据* @param con1 Consumer<String> 处理String类型函数式接口* @param con2 Consumer<String> 处理String类型函数式接口*/public static void testAndThen(String str, Consumer<String> con1, Consumer<String> con2) {/*con1.accept(str);con2.accept(str);允许组合拳con1.andThen(con2).andThen(con1).andThen(con2).andThen(con1).andThen(con2).accept(str);*/con1.andThen(con2).accept(str);}
}

代码示例

3.4 Predicate 判断数据是否合适,返回true/false

Predicate一般用于调节判断,过滤数据的方法
   函数式接口中指定的方法
   boolean test(T t);
      处理T类型数据,返回boolean true / false

import java.util.function.Predicate;/*** 演示Predicate<T>基本使用*      boolean test(T t)**/
public class Demo1 {public static void main(String[] args) {// Predicate函数式接口,使用Lambda表达式作为方法的参数boolean b = testPredicate("中国加油!!!",(str) -> {return str.contains("加油");});System.out.println("ret : " + b);System.out.println("---------------------------");/*优化Lambda表达式,因为是一个参数,小括号可以省略就一行代码,大括号可以省略return也可以省略*/testPredicate("中国加油!!!", str -> str.contains("加油"));}/*** 使用Predicate函数式接口利用boolean test(T t)对于当前数据进行判断操作,* 返回boolean类型数据** @param str 需要进行判断数据的String类型字符串* @param pre 处理使用Predicate函数式接口* @return 判断接口是否满足要求,满足返回true,不满足返回false*/public static boolean testPredicate(String str, Predicate<String> pre) {return pre.test(str);}
}

代码注释

and 与

代码示例:

import java.util.function.Predicate;/*** Predicate and使用* default修饰方法add(Predicate<T> pre)*      and就是逻辑运算符里面的 &&*      同真为真,有假【即】假*      需要对两个Predicate进行判断处理**      例如:*          pre1.test(str) && pre2.test(srt);*          ==> pre1.and(pre2).test(str);**/
public class Demo2 {public static void main(String[] args) {/*这里需要量Predicate接口,使用Lambda*/boolean ret = testAnd("不要搞事情了!!!",str -> str.length() > 5,str -> str.startsWith("赶紧"));System.out.println(ret);}/*** 组合判断** @param str  需要判断的字符串* @param pre1 判断方式1* @param pre2 判断方式2* @return 处理结果 true, false*/public static boolean testAnd(String str, Predicate<String> pre1, Predicate<String> pre2) {// return pre1.test(str) && pre2.test(str)return pre1.and(pre2).test(str);}
}

or 或

import java.util.function.Predicate;/*** Predicate or演示**/
public class Demo3 {public static void main(String[] args) {boolean ret = testOr("国外人羡慕不得~~",str -> str.length() < 10,str -> str.contains("美国"));System.out.println(ret);}/*** or 组合判断** @param str  需要判断的字符串* @param pre1 判断方式1* @param pre2 判断方式2* @return 处理结果 true, false*/public static boolean testOr(String str, Predicate<String> pre1, Predicate<String> pre2) {// return pre1.test(str) || pre2.test(str);return pre1.or(pre2).test(str);}
}

negate 非

import java.util.function.Predicate;/*** Predicate negate()操作**/
public class Demo4 {public static void main(String[] args) {boolean ret = testNegate("疫情会过去的!!!",str -> str.length() < 5);System.out.println(ret);}/*** negate操作** @param str 字符串* @param pre Predicate函数式接口* @return 处理结果*/public static boolean testNegate(String str, Predicate<String> pre) {// return !pre.test(str);return pre.negate().test(str);}
}

代码注释

3.4 Function<T,R> 类型转换

使用R apply(T t)
   转换指定类型T到R
代码示例:

import com.qfedu.c_supplier.Person;import java.util.function.Function;/*** Function<T, R> 函数式接口*      R apply(T)**/
public class Demo1 {public static void main(String[] args) {// Integer类型转换成一个StringString change = change(10, i -> i + "");System.out.println(change);// 利用函数式接口处理一个String类型,转换成对应的Person类型Person person1 = change("1,滴滴,16", str -> {String[] split = str.split(",");Person person = new Person();person.setId(Integer.parseInt(split[0]));person.setName(split[1]);person.setAge(Integer.parseInt(split[2]));return person;});System.out.println(person1);}/*** 转换格式的方法,要求数据从Integer类型转换到指定的String类型** @param i 需要转换的Integer类型* @param fun 转换使用的Function函数式接口* @return 返回值的是String类型*/public static String change(Integer i, Function<Integer, String> fun) {return fun.apply(i);}public static Person change(String str, Function<String, Person> fun) {return fun.apply(str);}
}

Person是一个自定义的类

andThen

代码示例:

import java.util.function.Function;/*** Function<T, R>*     default修饰andThen方法使用**/
public class Demo2 {public static void main(String[] args) {String s = testAndThen(10,i -> i + "",i -> i + "测试");System.out.println(s);}/*** 两次转换过程** @param i 需要处理的类型* @param fun1 Function函数接口* @param fun2 Function函数接口* @return String类型*/public static String testAndThen(int i, Function<Integer, String> fun1, Function<String, String> fun2) {// andThen使用,最后apply方法参数类型是fun1要求的转换参数类型return fun1.andThen(fun2).apply(i);}
}

Java中的函数式接口相关推荐

  1. Java 中的函数式编程

    1. 概述 在本教程中,我们将了解函数式编程范式的核心原则以及如何在 Java 编程语言中使用它们. 我们还将介绍一些高级函数式编程技术.这将帮助我们了解 Java 中的函数式编程的好处. 2. 什么 ...

  2. Java中的函数式编程(二)函数式接口Functional Interface

    写在前面 前面说过,判断一门语言是否支持函数式编程,一个重要的判断标准就是:它是否将函数看做是"第一等公民(first-class citizens)". 函数是"第一等 ...

  3. java 8 函数式接口_必看:通俗易懂地告诉你什么是java8中的“函数式接口”

    花10分钟认真的看完一篇文章,或许会有意想不到的收获 java8发布已经好几年了,相信很多小伙伴都使用过java8,java8这版本带来了很多新特性,其中一个就是"函数式接口",今 ...

  4. Java学习笔记——函数式接口

    一.函数式接口概述 函数式接口:有且仅有一个抽象方法的接口. Java中的函数式编程体现就是Lambda表达式,所以函数式接口就是可以适用于 Lambda表达式使用的接口.只有确保接口中有且仅有一个抽 ...

  5. java day23【函数式接口】

    第一章 函数式接口 1.1 概念 函数式接口在Java中是指:有且仅有一个抽象方法的接口. 函数式接口,即适用于函数式编程场景的接口.而Java中的函数式编程体现就是Lambda,所以函数式接口就是可 ...

  6. java8的函数式接口的好处_浅谈Java 8 新增函数式接口到底是什么

    从 Java 8 开始便出现了函数式接口(Functional Interface,以下简称FI) 定义为: 如果一个接口只有唯一的一个抽象接口,则称之为函数式接口.为了保证接口符合 FI ,通常会在 ...

  7. java新特性-函数式接口-作为方法参数-作为方法的返回值-常用函数式接口-Supplier-Consumer-Predicate-Function

    文章目录 函数式接口 概念 函数式接口作为方法参数 函数式接口作为方法的返回值 常用函数式接口 Supplier接口 常用函数式接口 Consumer 函数式接口之 Predicate接口 常用接口之 ...

  8. Java中的某些接口为什么没有任何方法?

    java中,有些接口内部没有声明任何方法,也就是说,实现这些接口的类不需要重写任何方法. 这些没有任何方法声明的接口又被叫做标识接口.标识接口对实现它的类没有任何语义上的要求,仅仅充当标识的作用,用来 ...

  9. Java中抽象类和接口在概念、语法和应用上的区别和关系

    2019独角兽企业重金招聘Python工程师标准>>> 春招开始了,盆友们都忙着准备笔试.准备面试,复习学过的知识点,当然我也不例外,在这里祝每一个"有心人"心想 ...

最新文章

  1. python中PIL.Image和OpenCV图像格式相互转换
  2. 湘西州计算机等级考试内容,2020年3月湖南省湘西州市计算机等级考试注意事项...
  3. Little Sub and Enigma
  4. java 文件拷贝保留原来的属性,Java - 复制JPG,同时保留所有文件属性
  5. [css] 如何解决css加载字体跨域的问题?
  6. Error querying database. Cause: java.lang.IllegalArgumentException:Failed to decrypt. 错误解决方案
  7. 阿里技术专家麒烨:修炼测试基本功
  8. SQL server 2005安装问题汇总
  9. socket编程(三)
  10. 读《C专家编程》笔记-关于内存泄漏
  11. centos7 定时清理内存
  12. 20多年老码农的IT学习之路
  13. javascript中 String对象方法(大小写转换、连接与拆分)
  14. 外显子名词解释_生物信息学常用名词解释(一)
  15. 医院预约挂号系统的设计
  16. sudo rm -f /
  17. 让ChatGPT成为你的人工智能好友
  18. Kmeans K均值聚类,OpenCV实现
  19. 搭建turnserver(转) 稍加整理
  20. SAP PP 第一节 PP后台配置

热门文章

  1. CG CTF witeup
  2. Could not establish trust relationship for the SSL/TLS secure channel
  3. 没有事业的女孩子(一位老总的感言)
  4. 篮球的基本规则是什么
  5. 滨州学院CSDN高校俱乐部第二次公开课——微信公众平台开发SAE使用
  6. android 键盘 输入图片,【图片】自定义属于自己的专属键盘的思路!!!(需要有android编程基础)【exagear吧】_百度贴吧...
  7. CRMEB多商户二开教程3
  8. 【工具配置】CLion编译c语言的配置
  9. NUC-家喻户晓的中药店
  10. 4K Video Downloader(4K视频下载器)V6.2.26版本发布