Java8-Function使用及Groovy闭包的代码示例
本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋。
概述###
在实际开发中,常常遇到使用模板模式的场景: 主体流程是不变的,变的只是其中要调用的具体方法。 其特征是:
BeginTodo ---> Something different to do ---> others todo ---> End
其中BeginTodo ,others todo,End 都是不变的,只有 Something different to do 是根据业务变化的。 如果采用 Java 来实现,通常要为 Something different to do 定义回调接口 Callback , 然后在主体流程中调用这个回调接口,而在实际业务中,创建 Callback 的实现类传入进去。
Java8 Function 以及闭包对此提供了更为简洁方便的语言支持。 Function 是Java8对函数的抽象,用于描述和接收任何单参数单返回的函数,类似于 Callback 的作用; 而在使用的时候,只要将方法引用或 lambda 表达式传给 Function 即可。
代码示例###
举例来说,要编写一个通用方法,实现多次执行同一个测试方法,统计失败次数。
Java-Function####
package com.xxx.trade;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.junit.Test;
import java.util.function.Function;
/**
* Created by shuqin on 16/11/15.
*/
public class GeneralExecTestMoreTimes extends TestCase {
public void execMoreTimes(Function f) {
execMoreTimes(f, new Object());
}
public void execMoreTimes(Function f, int num) {
execMoreTimes(f, null, num);
}
public void execMoreTimes(Function f, Object t) {
execMoreTimes(f, t, 20);
}
public void execMoreTimes(Function f, Object t, int num) {
int failed = 0;
for (int i = 0; i < num; i++) {
try {
f.apply(t);
} catch (AssertionFailedError afe) {
failed += 1;
} catch (Exception ex) {
failed += 1;
}
}
System.out.println("----- failed: " + failed + " -----");
assertEquals(0, failed);
}
@Test
public void testExecMoreTimes() {
execMoreTimes((o) -> {
System.out.println("haha");
return 1;
}, 5);
}
}
这里 execMoreTimes 方法接收一个函数式接口 Function 以及将应用于的参数 t 。 那么什么可以传给 Function 接口呢? 可以是任何单参数单返回值的函数,或者单参数单返回值的 lambda 表达式。例如代码中的 (o) -> { // some codes } 。
Groovy闭包####
如果使用 Groovy 编写闭包,会更简洁: 只要定义一个由大括号 {} 包围的代码块,并赋给一个变量即可(如下面的test1),甚至可以直接在函数里调用一个由大括号包围的代码块参数(如下面的test2)。 这样, 使用代码块或函数就会更加直接、灵活、自由,而不会受制于语法,也不需要定义一堆接口了。
package com.xxx.trade
import org.junit.Test
/**
* Created by shuqin on 16/11/15.
*/
class GeneralExecTestMoreTimesTest extends GeneralExecTestMoreTimes {
@Test
public void test1() {
def closure = {
System.out.println("here is test")
}
execMoreTimes(closure)
}
@Test
public void test2() {
execMoreTimes({
throw new Exception("throw exception in test")
})
}
}
应用场景####
函数接口可以用于任何使用回调接口的场景,一个典型的应用场景是批量处理。 比如有三个小组对同一个列表进行处理,一个用于状态同步,一个用于退款,一个用于取消。 那么,可以实现一个批量处理的通用函数,然后调用三个小组的自定义函数即可。
package zzz.study.utils;
import java.util.Arrays;
import java.util.List;
import java.util.function.Consumer;
/**
* Created by shuqin on 17/1/19.
*/
public class BatchProcessUtil {
public static String batchProcessOrders(Consumer<String> processFunction, List<String> orders) {
StringBuilder result = new StringBuilder();
for (String orderNo: orders) {
String orderNoTrimed = orderNo.trim();
try {
processFunction.accept(orderNo);
result.append(orderNoTrimed + " OK , 请稍后查看!\n");
} catch (Exception e) {
result.append(orderNoTrimed + " Failed, 请稍后重试!\n");
}
}
return result.toString();
}
public static void sync(String orderNo) {
System.out.println("sync order state " + orderNo);
}
public static void refund(String orderNo) {
System.out.println("refund for " + orderNo);
}
public static void cancel(String orderNo) {
System.out.println("cancel " + orderNo);
}
public static void main(String[] args) {
List<String> orders = Arrays.asList(new String[] {"E001", "E002", "E003"});
batchProcessOrders((orderNo) -> sync(orderNo), orders);
batchProcessOrders((orderNo) -> refund(orderNo), orders);
batchProcessOrders((orderNo) -> cancel(orderNo), orders);
}
}
输出是
sync order state E001
sync order state E002
sync order state E003
refund for E001
refund for E002
refund for E003
cancel E001
cancel E002
cancel E003
常用函数接口###
常用函数接口主要有:
- Consumer (接收单参数无返回值的函数或lambda表达式), 方法是 void accept(T t);
- BiConsumer<T, U> (接收双参数无返回值的函数或 lambda表达式),方法是 void accept(T t, U u) ;
- Function<T, R> (接收单参数有返回值的函数或lambda表达式), 方法是 R apply(T t);
- BiFunction<T, U, R> (接收双参数有返回值的函数或lambda表达式),方法是 R apply(T t, U u);
- Predicate (接收单参数返回布尔值的函数或lambda表达式),方法是 boolean test(T t);
- Supplier (无参数返回值的函数或 lambda), 方法是 T get();
- 接受原子类型参数的函数接口,这里不一一列举了。可参考 java8 package java.util.function;
小结###
为什么要使用 Function 以及闭包呢?
- 在语法上比定义回调接口、创建匿名类更加简洁;
- 尝试使用新的语言特性,理解多样化的编程思想,提升编程表达能力。
Java8-Function使用及Groovy闭包的代码示例的更多相关文章
- Java8函数接口实现回调及Groovy闭包的代码示例
本文适用于想要了解Java8 Function接口编程及闭包表达式的筒鞋. 概述 在实际开发中,常常遇到使用模板模式的场景: 主体流程是不变的,变的只是其中要调用的具体方法. 其特征是: Begi ...
- java代码之美(15)---Java8 Function、Consumer、Supplier
Java8 Function.Consumer.Supplier 有关JDK8新特性之前写了三篇博客: 1.java代码之美(1)---Java8 Lambda 2.java代码之美(2)---Jav ...
- java代码(15) ---java8 Function 、Consumer 、Supplier
Java8 Function.Consumer.Supplier 有关JDK8新特性之前还有三篇博客: 1,java代码(1)---Java8 Lambda 2,java代码(2)---Java8 S ...
- 谈谈Groovy闭包
A closure is a function with variables bound to a context or environment in which it executes. 概述 闭包 ...
- 使用yaml+groovy实现Java代码可配置化
背景与目标 在使用函数接口和枚举实现配置式编程(Java与Scala实现),使用了函数接口和枚举实现了配置式编程.读者可先阅读此文,再来阅读本文. 有时,需要将一些业务逻辑,使用配置化的方式抽离出来, ...
- Groovy闭包详解
Groovy闭包是一种可执行代码块的方法,闭包也是对象,可以向方法一样传递参数,因为闭包也是对象,因此可以在需要的时候执行,像方法一样闭包可以传递一个或多个参数.闭包最常见的用途就是处理集合,可以遍历 ...
- 通过Groovy来消除代码噪声
通过Groovy来消除代码噪声 Java是在JVM上运行的最广泛使用的编程语言.不过,还有很多其他基于JVM的语言,比如Groovy,Scala,JRuby,Jython,Kotlin等等.其中,Gr ...
- Groovy学习:第一章 用Groovy简化Java代码
1. Groovy的安装 目前Groovy的最新版本为2.1.2版,下载地址为:http://groovy.codehaus.org/Download下载后解压groovy-binary-2.1.2. ...
- SELECT控件操作的JS代码示例
SELECT控件操作的JS代码示例 1 检测是否有选中 if(objSelect.selectedIndex > -1) { //说明选中 } else { //说明没有选中 } 2.动态创建s ...
随机推荐
- 键盘事件触发的兼容tips
在firefox中 退格键 enter del tab 这些非字符触发编码为0 然而在Safari3以下 是8
- linux 压缩 解压zip 命令
将当前目录下的所有文件和文件夹全部压缩成test.zip文件,-r表示递归压缩子目录下所有文件zip -r test.zip ./* 打包目录zip test2.zip test2/*解压test.z ...
- git clone时,报403错误,完美解决方案
首先命令行操作结果如下: root@zhiren-PowerEdge-T110-II:/zrun# git clone https://git.coding.net/xxxxxxxx/xxxx.git ...
- 两个有意思的模式在ECMAScript中的实现
简介 本篇文章对设计模式进行了筛选, 只列举两个有意思(坑)的设计实现, 如有错误愿闻其详. 构造函数 ECMAScript中的构造函数和其他语言的有那么点特别之处,可以认为, 一个函数, 如果被以n ...
- SpringBoot RESTful 应用中的异常处理小结
转载:https://segmentfault.com/a/1190000006749441 @ControllerAdvice 和 @ExceptionHandler 的区别 ExceptionHa ...
- 查看apache、linux、kernel、nginx等版本
查看apache版本 /usr/sbin/apachectl -v httpd -v 安装目录,使用apachectl -v 查看mysql版本 mysql –help | grep Distri ...
- NuGet控制台有几个常用命令
NuGet控制台有几个常用命令 Get-Package 获取当前项目已经安装的类库 Install-Package 安装指定类库,命令格式如下:Install-Package 类库ID,如Instal ...
- jQuery 隐藏/显示
1.如何隐藏部分文本(简单案例) //样式 <style type="text/css"> div.ex { bac ...
- IOS 支持HTTPS调用(AFNetWorking框架)
1.ATS开关开启2.manager.securityPolicy.allowInvalidCertificates = YES; manager.securityPolicy.validatesDo ...
- Spring事务传播属性
Spring 对事务控制的支持统一在 TransactionDefinition 类中描述,该类有以下几个重要的接口方法: int getPropagationBehavior():事务的传播行为 i ...