前言

很多编程语言可以把函数当作参数进行传递,例如js中事件触发后的函数调用、C语言中的函数指针,都可以完成函数的传递。但是在Java里一直没有一个传函数的标准,直到jdk8开始,有了函数传递的一套规范。

1. lambda表达式

1.1 支持版本

JDK8及以上

1.2 概念

也叫箭头函数,得益于javac的类型推断,编译器能够根据上下文信息推断出参数的类型。本质上是一个可传递的匿名函数,但是区别于匿名内部类,它不会编译出额外的类,例如 Main$1.class

1.3 基本语法

基本形式:parameter -> expression完整形式:(Type parameter1, Type parameter2) -> { code block; return result; }省略参数类型: (parameter1, parameter2) -> { code block; return result; }单参数省略参数括号:parameter -> { code block; return result; }只有一句表达式省略方法体括号:(Type parameter1, Type parameter2) -> expression

1.4 省略关键

小括号内参数的类型可以省略
    如果小括号内有且仅有一个参数,则小括号可以省略
    如果方法体大括号内有且仅有一个语句,则无论是否有返回值,都可以省略大括号、return关键字及分号

1.5 注意事项

lambda表达式一般用作接口的实现上,用于简化代码。

new Thread(new Runnable() {@Overridepublic void run() {}
});//通过匿名内部类创建Runnable接口实现类作为Thread的参数new Thread(() -> {
});//通过Labmda表达式创建Thread的参数// Thread一定是只有一个抽象方法

lambda表达式往往是使用在方法内部的方法,因此lambda表达式里面声明的基本类型变量都会分配到栈上,每个都是线程安全的,因为栈上的变量不共享。如果lambda表达式方法内部需要修改外部变量的状态,这个变量要保证是在堆上分配,且要注意线程安全问题。

2. 接口式函数

2.1 支持版本

JDK8及以上

2.2 概念

JDK8新增了@FunctionalInterface,用来标注一个接口是符合“函数式”的。即,自定义接口有且只有一个抽象方法(可以理解为,创建此接口的对象只要实现一个方法即可,可能因为lambda只能有一个函数),就认为这个接口是符合函数式的,可以使用lambda语法。

2.3 基本语法

定义一个普通接口,再定义一个抽象方法即可。这里强调因为JDK8版本的接口可能不止有抽象方法,还能有默认方法和静态方法,这些特性在JDK7里是不存在的。

2.4 default、static

JDK8的新特性,接口可以定义方法的实现了。default修饰的方法叫默认方法,这种方法不需要手动实现,也不会报错,如果默认方法不能满足需求,重写就好了。
    JDK8的新特性,接口支持定义static方法,调用方法和普通静态方法调用一样:接口名.静态方法名。但是要注意,接口的实现类是没有这个静态方法的。强行调用会报错:This static method of interface 接口名 can only be accessed as 接口名.静态方法名

2.5 示例代码

@FunctionalInterface
public interface Operator {int operation(int a, int b);default void sayHello() {System.out.println("Hello everyone.");}static void sayBye() {System.out.println("Bye everyone.");}
}

3. 函数式编程

3.1 支持版本

JDK8及以上

3.2 概念

函数像变量一样使用,能当作入参也能作为返回函数

3.3 实现思路

借助“接口式函数”和lambda表达式,创建一个函数的调用句柄,参数列表处用接口式函数作为入参,方法体里用接口的唯一抽象方法执行业务逻辑。

3.3 示例代码

3.1 接口部分

// 添加FunctionalInterface注解,表示这是一个方法式接口,不加也行,加上可以让编译器检查语法
// 建议添加,以防他人修改接口
@FunctionalInterface
public interface Operator {// 只有这个方法是抽象的int operation(int a, int b);// 默认方法,子类可以不实现直接用,不满足需求可以重写default void sayHello() {System.out.println("Hello everyone.");}// 静态方法,子类不可用,只能 Operator.sayBye()static void sayBye() {System.out.println("Bye everyone.");}
}

3.2 接口式函数及调用

public class CalculateDemo {public static void main(String [] s) {/*** define anonymous function*/// +Operator add = (int a, int b) -> a+b;// FunctionTest 未省略方法体的括号及返回 = (int a, int b) -> {return a+b;};// -// Operator subtract = (int a, int b) -> a-b;// *// Operator multiply = (int a, int b) -> a*b;// /// Operator divide = (int a, int b) -> a/b;// %// Operator mod = (int a, int b) -> a%b;// 定义入参int a = 10;int b = 2;// 调用计算函数时,把操作函数传过去,这里就测了一个相加的// add可以看作是一个函数,但是它还是一个对象calculate(add, a,  b);}private static void calculate(Operator oper, int a, int b) {// 调用default方法,没重写过的oper.sayHello();// 实际上是调用的Operator对象的那个抽象方法int result = oper.operation(a,b);System.out.println(result);
//      oper.sayBye(); 报错:This static method of interface Operator can only be accessed as Operator.sayBye// 静态方法只能这样调用,子类是调用不到的Operator.sayBye();}}

4.java.util.function包主要类

4.1 - 4.4 示例代码均来自Java8之Consumer、Supplier、Predicate和Function攻略 - 掘金

4.1 Supplier

4.1.1 概念

provider,只出不入的一个类型,负责对外提供数据,类似信号发生器、工厂。

4.1.2 示例代码

    @Testpublic void test_Supplier() {//① 使用Supplier接口实现方法,只有一个get方法,无参数,返回一个值Supplier<Integer> supplier = new Supplier<Integer>() {@Overridepublic Integer get() {//返回一个随机值return new Random().nextInt();}};System.out.println(supplier.get());System.out.println("********************");//② 使用lambda表达式,supplier = () -> new Random().nextInt();System.out.println(supplier.get());System.out.println("********************");//③ 使用方法引用Supplier<Double> supplier2 = Math::random;System.out.println(supplier2.get());}

4.2 Consumer

4.2.1 概念

consumer,消费者,只入不出。负责使用数据,并不会返回。

4.2.2 示例代码

    @Testpublic void test_Consumer() {//① 使用consumer接口实现方法Consumer<String> consumer = new Consumer<String>() {@Overridepublic void accept(String s) {System.out.println(s);}};Stream<String> stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");stream.forEach(consumer);System.out.println("********************");//② 使用lambda表达式,forEach方法需要的就是一个Consumer接口stream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");Consumer<String> consumer1 = (s) -> System.out.println(s);//lambda表达式返回的就是一个Consumer接口stream.forEach(consumer1);//更直接的方式//stream.forEach((s) -> System.out.println(s));System.out.println("********************");//③ 使用方法引用,方法引用也是一个consumerstream = Stream.of("aaa", "bbb", "ddd", "ccc", "fff");Consumer consumer2 = System.out::println;stream.forEach(consumer);//更直接的方式//stream.forEach(System.out::println);}

4.3 Predicate

4.3.1 概念

直译是谓词,理解为判断器就行了。有输入有输出,但是输出一定是bool型。

4.3.2 示例代码

   @Testpublic void test_Predicate() {//① 使用Predicate接口实现方法,只有一个test方法,传入一个参数,返回一个bool值Predicate<Integer> predicate = new Predicate<Integer>() {@Overridepublic boolean test(Integer integer) {if(integer > 5){return true;}return false;}};System.out.println(predicate.test(6));System.out.println("********************");//② 使用lambda表达式,predicate = (t) -> t > 5;System.out.println(predicate.test(1));System.out.println("********************");}

4.4 Functional

4.4.1 概念

有输入有输出,且类型可以自定义的一个类型。

4.4.2 示例代码

   @Testpublic void test_Function() {//① 使用map方法,泛型的第一个参数是转换前的类型,第二个是转化后的类型Function<String, Integer> function = new Function<String, Integer>() {@Overridepublic Integer apply(String s) {return s.length();//获取每个字符串的长度,并且返回}};Stream<String> stream = Stream.of("aaa", "bbbbb", "ccccccv");Stream<Integer> stream1 = stream.map(function);stream1.forEach(System.out::println);System.out.println("********************");}

4.5 整体示例代码

    @Testpublic void testFunctions() {// provider.getSupplier<Integer> s  = () -> new Random().nextInt();// consumer.acceptConsumer<String> c = System.out::println;// provideInteger integer = s.get();// functionalFunction<Integer, String> f = i -> {if (i >= 0) {return "functional判断为正整数";} else {return "functional判断为负数";}};// functionc.accept(f.apply(integer));// judgment.testPredicate<Integer> p = (i) -> i>0;c.accept(integer+"");// predicateif (p.test(integer)) {c.accept("predicate判断为正整数");} else {c.accept("predicate判断为负数");}}

5. 总结

Java的这个函数式编程,总感觉还是很拗,说是传递的函数,实际上是传递函数所属的对象,然后调用接口,并不是纯的传递函数,只不过是借助lambda简化了一下写法,或者是终于官方提供了一个“传函数”的规范。

最大的好处是能通过Stream方便的处理数据,且性能更好。

6 . 示例

6.1 两次循环过滤数据

public class Test1 {public static void main(String[] args) {// 字典List<Integer> l1 = new ArrayList<Integer>();l1.add(3);l1.add(4);// 数据集合List<T> l2 = new ArrayList<T>();l2.add(new T(1, "one"));l2.add(new T(2, "two"));l2.add(new T(3, "three"));l2.add(new T(4, "four"));l2.add(new T(5, "five"));l2.add(new T(6, "six"));l2.add(new T(7, "seven"));l2.add(new T(8, "eight"));// 判断哪些对象是在字典中// 先把数据集合转化成流,开始循环List<T> nl2 = l2.stream().filter(tItem -> {// 把字典转换成流,并判断是否和数据流中有匹配return l1.stream().anyMatch(i -> tItem.key == i);// 把过滤后的数据返回给一个新的数据集合}).collect(Collectors.toList());nl2.stream().forEach(i -> {System.out.println(i.key+"---"+i.value);});}
}class T {public T(Integer key, String value) {super();this.key = key;this.value = value;}public Integer key;public String value;
}

Java 函数式编程合集相关推荐

  1. java函数式编程及集合流操作

    函数式编程及集合流操作 一. 单选题(共2题,16.6分) 1. (单选题)函数式编程是 A. 一种编程语言 B. 一种程序设计思想 C. 面向对象程序设计的一种实现 D. Java操作集合的工具框架 ...

  2. Java面试核心知识点(283页)Java面试题合集最新版(485页)

    阿里.腾讯两大互联网企业传来裁员消息,很多人都陷入担心,不安情绪蔓延-- 其实大家应该更冷静和理性地看待大厂裁员.每年三四月都是大厂人员调整期,这个季节是各个公司战略调整.战略规划的一个关键期,肯定会 ...

  3. 【毕设|Java项目开发合集】(附源码)

    [毕设|Java项目开发合集] 14个Java项目(附源码)助你轻松搞定毕业设计! 1.新冠疫情统计系统 2.家教系统 3.进销存管理系统 4.饮食分享平台 5.宠物领养平台 6.销售评价系统 7.酒 ...

  4. Java 函数式编程和 lambda 表达式

    为什么要使用函数式编程 函数式编程更多时候是一种编程的思维方式,是种方法论.函数式与命令式编程的区别主要在于:函数式编程是告诉代码你要做什么,而命令式编程则是告诉代码要怎么做.说白了,函数式编程是基于 ...

  5. Java函数式编程知识分享!

    Java是一种计算机编程语言,可用于编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序等,是IT开发行业中最受欢迎的编程语言之一.想要学好Java必须要一步一个脚印打好基础.积攒实战经验 ...

  6. java全局变量怎么定义_Java开发知识点:如何理解Java函数式编程?

    Java是一种计算机编程语言,可用于编写桌面应用程序.Web应用程序.分布式系统和嵌入式系统应用程序等,是IT开发行业中最受欢迎的编程语言之一.想要学好Java必须要一步一个脚印打好基础.积攒实战经验 ...

  7. Java 函数式编程入门

    Java 函数式编程入门 函数式编程实战 改进 完整代码   像 JavaScript 这种语言很早就支持闭包了,虽然 C++ 很早就有了函数指针,Java 也很早就提供了反射中的 Method 类, ...

  8. 《深入理解Java函数式编程》系列文章

    Introduction 本系列文将帮助你理解Java函数式编程的用法.原理. 本文受启发于JavaOne 2016关于Lambda表达式的相关主题演讲Lambdas and Functional P ...

  9. java 函数式编程 示例_功能Java示例 第8部分–更多纯函数

    java 函数式编程 示例 这是第8部分,该系列的最后一部分称为"示例功能Java". 我在本系列的每个部分中开发的示例是某种"提要处理程序",用于处理文档. ...

最新文章

  1. 完整约束三(学习笔记)
  2. 《Raspberry Pi用户指南》——2.4 使用外部存储设备
  3. C# Socket编程
  4. Ajax ToolKit --- ModelPopupExtender应用经验二则
  5. 她,既是一个风华绝代的演员,更是WiFi之母...
  6. 一步步编写操作系统 45 用c语言编写内核2
  7. Spring 的 ApplicationEvent and ApplicationListener
  8. Java基础markdown笔记整理(尚硅谷康师傅)
  9. google 手机号码校验库libphonenumber
  10. Mongodb 可视化工具 mongochef
  11. 笔记本外接2K显示器
  12. linux脚本判断奇数偶数,Bash Shell -- 奇数 偶数 之和计算
  13. WESHOP | 基于微服务的小程序商城系统
  14. 如何删除我们的应用在 AppStore 中的负面评论
  15. codeforces-1202C-WASD-string
  16. 我的2007-高开低走,无甚成就
  17. HDU-2017 多校训练赛9-1005-FFF at Valentine
  18. 51单片机通过WIFI模块ESP8266控制LED灯
  19. lol最克制诺手的英雄_LOL:对线很“无解”的5个英雄,其实他们都有克星,诺手只怕它!...
  20. ReactNative系列之十九表情emoji与文字混排的两种方案实现

热门文章

  1. html a标签怎样设置宽高,a标签如何设置高度和宽度
  2. 如何使用Python对中文文档进行可视化的主题建模?
  3. win10应用 UWP 使用MD5算法
  4. user_constraints,user_cons_columns
  5. Linux网卡绑定(bonding)配置
  6. Unity3D开发之Error while reading movie Bug解决
  7. 笔记本电脑计算机没了,如果笔记本电脑很长时间没有关闭,它将对笔记本计算机产生什么影响?看了很久的经验...
  8. 关注你要的结果,而不要在意别人的态度
  9. JTAG电阻上下拉的问题
  10. 慈文传媒马中骏累计质押5838万股份 占总股本逾12%