Java学习-函数式接口
Java学习-函数式接口
- 1.函数式接口
- 1.1概述
- 1.2语法
- 1.3@FunctionalInterface
- 2. 函数式编程
- 2.1Lambda的延迟执行
- 2.2 使用Lambda作为参数和返回值
- Lambda作为参数
- Lambda作为返回值
- 3.Java常用函数式接口
- 3.1 Supplier接口
- 3.2 Consumer接口
- 3.3 Predicate接口
- 3.4 Function接口
1.函数式接口
1.1概述
函数式接口在Java中是指:有且仅有一个抽象方法的接口。 函数式接口,即适用于函数式编程场景的接口。而Java中的函数式编程体现就是Lambda,所以函数式接口就是可以适用于Lambda使用的接口。只有确保接口中有且仅有一个抽象方法,Java中的Lambda才能顺利地进行推导。
当然接口中可以包含其它的方法(默认,静态,私有)
1.2语法
只要确保接口中有且仅有一个抽象方法即可:
修饰符 interface 接口名称 {public abstract 返回值类型 方法名称(可选参数信息);// 其他非抽象方法内容}
1.3@FunctionalInterface
当我们定义一个函数式接口的时候,我们可以使用注解 @FunctionalInterface 来注释
@FunctionalInterface:
检测是否是函数时接口- 如果接口有且只有一个抽象方法,编译成功
- 当没有抽象方法,或则多余一个抽象方法的时候,会编译不通过
@FunctionalInterface
public interface MyFunctionInterface {public abstract void show();
}
2. 函数式编程
2.1Lambda的延迟执行
- 性能浪费的日志案例
/*性能浪费日志案例:日志可以帮助我们快速定位问题,记录程序运行过程的情况,以便项目的监控和优化一种典型的场景就是对参数进行有条件的使用,例如对日志的消息凭借后,满足条件情况下打印日志*/
public class FuncDemo {public static void main(String[] args) {String msgA = "Hello";String msgB = "World";String msgC = "Java";log(1, msgA + msgB + msgC);/*无论级别是否满足要求,作为 log 方法的第二个参数,三个字符串一定会首先被拼接并传入方
法内,然后才会进行级别判断。如果级别不符合要求,那么字符串的拼接操作就白做了,存在性能浪费。*///使用Lambda表达式实现性能的优化,当不满足条件的时候,字符串拼接操作是不会执行的log2(1, () -> msgA + msgB + msgC);}private static void log(int level, String msg) {if (level == 1) {System.out.println(msg);}}private static void log2(int level, MessageBuilder messageBuilder) {if (level == 1) {System.out.println(messageBuilder.buildMessage());}}}
2.2 使用Lambda作为参数和返回值
Lambda作为参数
//首先定义一个函数式接口
@FunctionalInterface
public interface MyFunctionInterface {public abstract void show();
}
//定义一个方法
public static void showMethod(MyFunctionInterface myFunctionInterface){myFunctionInterface.show();}//测试代码
//接口的作为参数的实现方式//1.直接传递实现接口的实现类showMethod(new MyFunctionInterfaceImpl());//2.使用匿名内部类的方式来实现showMethod(new MyFunctionInterface() {@Overridepublic void show() {System.out.println("匿名内部类的方式来实现接口");}});//3.使用Lambda的方式来实现接口(只能函数式接口)showMethod(() -> {System.out.println("使用Lambda表达式来实现函数式接口");});//4.Lambda表达式的简化实现showMethod(() -> System.out.println("使用Lambda的简化方式来实现函数式接口"));
Lambda作为返回值
/*定义一个使用Lambda表达式作为返回参数的方法*/public static Comparator<String> customComparator() {//1.使用匿名内部类的方式来返回一个比较器
// return new Comparator<String>() {// @Override
// public int compare(String o1, String o2) {// return o1.length() - o2.length();
// }
// };//2.使用Lambda表示的方式返回
// return (String o1, String o2) -> {// return o1.length() - o2.length();
// };//3.使用Lambda的简化方式return (String o1, String o2) -> o1.length() - o2.length();}//Lambda表达式作为返回值的测试String[] temp = {"aaaa","b","cccccccc","dddddddddd"};System.out.println("没有排序前的字符串数组=====" + Arrays.toString(temp));Arrays.sort(temp, customComparator());System.out.println("排序后的字符串数组=======" + Arrays.toString(temp));
3.Java常用函数式接口
JDK提供了大量常用的函数式接口以丰富Lambda的典型使用场景,它们主要在 java.util.function 包中被提供。 下面是最简单的几个接口及使用示例。
3.1 Supplier接口
java.util.function.Supplier 接口仅包含一个无参的方法: T get() 。用来获取一个泛型参数指定类型的对 象数据。由于这是一个函数式接口,这也就意味着对应的Lambda表达式需要“对外提供”一个符合泛型类型的对象 数据。
- 代码示例:
public class SupplierDemo {public static void main(String[] args) {//测试Supplier的简单用法supplierTest();supplierExample();}/*求数组中元素的最大值*/public static void supplierExample(){int[] arr = {100,80,120,60};int maxCount = getMax(arr, () ->{int max = arr[0];for (int i = 1; i < arr.length-1; i++) {if (max > arr[i]) {max = arr[i];}}return max;});}public static int getMax(int[] arr, Supplier<Integer> supplier) {return supplier.get();}/*supplier 的简单运用代码*/public static void supplierTest() {/*Supplier: java.util.function.Supplier<T> 接口仅包含一个无参的方法: T get()用来获取一个泛型参数指定类型的对 象数据,生产数据*///简单使用-> 使用匿名内部类的方式int count = getCount(new Supplier<Integer>() {@Overridepublic Integer get() {return 20;}});System.out.println("count======" + count);//使用Lambda表达式来使用int count2 = getCount(() -> {return 30;});System.out.println("Lambda表达式====" + count2);//优化int count3 = getCount(() -> 60);System.out.println("优化后lambda表达式======" + count3);}/*使用Supplier接口生产一个Int类型的数据*/public static int getCount(Supplier<Integer> supplier) {return supplier.get();}}
3.2 Consumer接口
java.util.function.Consumer 接口则正好与Supplier接口相反,它不是生产一个数据,而是消费一个数据, 其数据类型由泛型决定。
- 代码示例
public class ConsumerDemo {public static void main(String[] args) {//1.Consumer:接口与Supplier接口正好相反 是消费数据consumerTest("我爱Java", new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println("匿名内部类实现====" + s);}});consumerTest("我爱Java",(String s) -> {System.out.println("Lambda表达式=====" + s);});//优化consumerTest("我爱Java",s -> System.out.println("Lambda表达式优化之后=====" + s));//Consumer中的默认方法测试 andThen() 方式consumerTest2("我爱Java",(String s) -> {System.out.println("andThen first====" + s);},(String s) -> {System.out.println("andThen seconde=====" + s);});}public static void consumerTest(String testString, Consumer<String> consumer) {consumer.accept(testString);}public static void consumerTest2(String testString, Consumer<String> consumer, Consumer<String> consumer2) {consumer.andThen(consumer2).accept(testString);}
}
3.3 Predicate接口
有时候我们需要对某种类型的数据进行判断,从而得到一个boolean值结果。这时可以使用
java.util.function.Predicate 接口。
*代码案例:
public class PredicateDemo {public static void main(String[] args) {//测试判断字符串中包含不包含aString str = "dsadsad";boolean b = predicateTest(str, s -> {return s.contains("a");});System.out.println(b);//判断字符串里面是否同时包含s 还包含b and方法boolean b1 = predicateTest2(str, s -> s.contains("s"), s -> s.contains("b"));System.out.println(b1);//使用or方法来判断boolean b2 = predicateTest2(str, s -> s.contains("s"), s -> s.contains("d"));System.out.println(b2);//negate() 非的结果 结果取反boolean b3 = predicateTest(str, s -> s.contains("x"));System.out.println(b3);}public static boolean predicateTest(String testString, Predicate<String> predicate) {return predicate.test(testString);}public static boolean predicateTest2(String testString, Predicate<String> predicate, Predicate<String> predicate2) {return predicate.and(predicate2).test(testString);}public static boolean predicateTest3(String testString, Predicate<String> predicate, Predicate<String> predicate2) {return predicate.or(predicate2).test(testString);}}
3.4 Function接口
java.util.function.Function<T,R> 接口用来根据一个类型的数据得到另一个类型的数据,前者称为前置条件,后者称为后置条件。
- 代码案例:
public class FunctionDemo {public static void main(String[] args) {int count = functionTest("123", s -> Integer.parseInt(s));System.out.println("count======" + count);//anThen的方法连续转转 谁在前 谁先转换 第一步转换完成之后s编程Integer类型 , 在接着把Integer转换成String类型String str = functionTest2("123",s -> Integer.parseInt(s), s -> String.valueOf(count));System.out.println("str====== " + str);}/*Function<String, Integer>: 把String类型的数据转换成为Integer类型的数据 apply()方法*/public static int functionTest(String testString, Function<String, Integer> function) {return function.apply(testString);}public static String functionTest2(String testString, Function<String, Integer> function, Function<Integer, String> function2) {return function.andThen(function2).apply(testString);}}
Java学习-函数式接口相关推荐
- 学习 Java 8 - 函数式接口 Lambda
学习 Java 8 - 函数式接口 Java 8 引入了函数式接口的概念.函数式接口其实就是只包含一个抽象方法的普通 Java 接口.在没有引入函数式接口之前,我们通常使用内部类和匿名类来实现类似的功 ...
- 高级JAVA - 利用函数式接口实现通用的取并集/交集/差集进阶版
在前文(高级JAVA - 利用函数式接口实现通用的取并集/交集/差集)中我们实现了利用函数式接口获取交集/差集 , 但是只能全部生成 , 假如我们只需要一个交集的话 , 所有代码仍然会执行一次 . 比 ...
- java中函数式接口的使用
java中函数式接口的使用 一.自己创建的函数式接口 1.1 概念 只存在一个抽象方法的接口. 1.2 使用步骤: 1.创建函数式接口,创建格式参照使用格式. 2.创建一个实例类 3.在实例类中使用函 ...
- Java之函数式接口(FunctionalInterface)
Java之函数式接口(FunctionalInterface) 1. FunctionalInterface是什么? FunctionalInterface 中文称之为 函数式接口.是Java新特性之 ...
- java 8 函数式接口_必看:通俗易懂地告诉你什么是java8中的“函数式接口”
花10分钟认真的看完一篇文章,或许会有意想不到的收获 java8发布已经好几年了,相信很多小伙伴都使用过java8,java8这版本带来了很多新特性,其中一个就是"函数式接口",今 ...
- Java四大函数式接口
Java8函数式接口 1. Consumer<T> 消费型接口 2. Supplier <R> 供给型接口 3. Function<T, R> 函数型接口 4. P ...
- 【Java】函数式接口与Lambda表达式
函数式接口--@FunctionalInterface Code @FunctionalInterface interface IService {void say(String message); ...
- 高级JAVA - 利用函数式接口实现通用的取并集/交集/差集
package com.xing.dto;import com.xing.common.utils.XDataUtil; import lombok.Data;import java.util.Arr ...
- java自定义函数式接口
⾃定义lambda接⼝流程 定义⼀个函数式接⼝ 需要标注此接⼝ @FunctionalInterface,否则万⼀团队成员在接⼝上加 了其他⽅法则容易出故障 编写⼀个⽅法,输⼊需要操做的数据和接⼝ 在 ...
- java 常用 函数式接口_「java8系列」神奇的函数式接口
前言 在上一篇Lambda的讲解中我们就提到过函数式接口,比如:Consumer consumer = (s) -> System.out.println(s);其中Consumer就是一个函数 ...
最新文章
- Oracle架构实现原理、含五大进程解析(图文详解)
- git撤销/回退操作
- 亲测有用的markdown博客生成器
- Spring:使基于Java的配置更加优雅
- c# mysql sdr_C#结合数据库实现验证识别ID卡内容的方法
- node mysql 模块 封装_node.js基于工厂方法的mysql模块封装
- python卸载错误_卸载python后导致yum无法使用的解决办法 - Python - 服务器之家
- Flash Cs4安装之后打不开(启动界面一闪而过)
- springboot幼儿园幼儿基本信息管理系统毕业设计源码201126
- 冰封王座人工只能_魔兽争霸3玩家热议 人工智能能否轻松战war3胜职业选手?
- 日本华人IT派遣那点事儿(2)
- 2023 HGAME网络攻防大赛wp
- HTML简易奥运五环
- python图案填充_Python:使用matplotlib颜色和图案填充字典
- 360浏览器查看服务器响应内容,360浏览器怎么看3个月以前的浏览记录?
- 计算机工资高的岗位,毕业五年后工资最高的4大专业,就业容易岗位多
- 通常一个 Xml 映射文件,都会写一个 Dao 接口与之对应, 请问,这个 Dao 接口的工作原理是什么?Dao 接口里的方法, 参数不同时,方法能重载吗?
- python——删除文件夹下的所有文件和子文件夹(含代码)
- 专利对于2023年的高新技术企业认定到底有多重要?
- Vue生命周期及其钩子函数