Shellbye.github.io
Shellbye.github.io copied to clipboard
Java 8 通过 FunctionalInterface 实现函数作为参数传递
日常工作中,我们可能会遇到不少业务场景,他们的整体结构都是一样的,只是有一小部分有差别。我们把这样的场景抽象成以下的代码段
long s1 = 0;
// 1 + 2*2 + 3*3*3 + 4*4 + 5*5*5 + 6*6 + 7*7*7 + 8*8 + 9*9*9
for (Integer integer : integerList) {
if (integer % 2 == 0) {
s1 += integer * integer;
} else {
s1 += integer * integer * integer;
}
}
System.out.println(s1);
long s2 = 0;
// 1*3 + 2*2 + 3*3 + 4*2 + 5*3 + 6*2 + 7*3 + 8*2 + 9*3
for (Integer integer : integerList) {
if (integer % 2 == 0) {
s2 += integer * 2;
} else {
s2 += integer * 3;
}
}
System.out.println(s2);
这里为了表达上的简洁性,我们把很多复杂的代码抽象成了一个for循环加一个if else,实际的工作中,这部分重复代码可能比较复杂,这里我们只表达相应的意思就行。在上面的代码中,我们对数组中的偶数和奇数进行了两次不同的操作,而且这两次还很难通过简单的提取公共代码来提高复用性,因为它们的公共代码中有一部分不是对象或者变量,而是函数,这在Java 8之前还比较麻烦,但是在Java 8之后,我们可以利用函数式编程的思想,把函数作为一个参数进行传递。
下面我们来看具体的实现
package com.shellbye;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
@FunctionalInterface
interface IntOddOperator<R> {
long doIfOdd(R r);
}
@FunctionalInterface
interface IntEvenOperator<R> {
long doIfEven(R r);
}
public class Main {
public static void old(List<Integer> integerList) {
long s1 = 0;
// 1 + 2*2 + 3*3*3 + 4*4 + 5*5*5 + 6*6 + 7*7*7 + 8*8 + 9*9*9
for (Integer integer : integerList) {
if (integer % 2 == 0) {
s1 += integer * integer;
} else {
s1 += integer * integer * integer;
}
}
System.out.println(s1);
long s2 = 0;
// 1*3 + 2*2 + 3*3 + 4*2 + 5*3 + 6*2 + 7*3 + 8*2 + 9*3
for (Integer integer : integerList) {
if (integer % 2 == 0) {
s2 += integer * 2;
} else {
s2 += integer * 3;
}
}
System.out.println(s2);
}
public static void main(String[] args) {
List<Integer> integerList = new ArrayList<Integer>(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9));
old(integerList);
common(integerList, Main::oddFunc1, Main::evenFunc1);
common(integerList, Main::oddFunc2, Main::evenFunc2);
}
public static void common(
List<Integer> integerList, IntOddOperator<Integer> intOddOperator,
IntEvenOperator<Integer> intEvenOperator) {
long sum = 0;
for (Integer integer : integerList) {
if (integer % 2 == 0) {
sum += intEvenOperator.doIfEven(integer);
} else {
sum += intOddOperator.doIfOdd(integer);
}
}
System.out.println(sum);
}
public static int evenFunc1(Integer integer) {
return integer * integer;
}
public static int oddFunc1(Integer integer) {
return integer * integer * integer;
}
public static int evenFunc2(Integer integer) {
return integer * 2;
}
public static int oddFunc2(Integer integer) {
return integer * 3;
}
}
首先我们定义了针对奇数和偶数不同的处理方式的两个接口IntOddOperator和IntEvenOperator,并在其内部定义了具体的方法签名。
@FunctionalInterface
interface IntOddOperator<R> {
long doIfOdd(R r);
}
@FunctionalInterface
interface IntEvenOperator<R> {
long doIfEven(R r);
}
注意其中的FunctionalInterface很重要。然后在我们抽出来的公共代码common中的具体调用位置,调用接口中定义的两个函数。
public static void common(
List<Integer> integerList, IntOddOperator<Integer> intOddOperator,
IntEvenOperator<Integer> intEvenOperator) {
long sum = 0;
for (Integer integer : integerList) {
if (integer % 2 == 0) {
sum += intEvenOperator.doIfEven(integer);
} else {
sum += intOddOperator.doIfOdd(integer);
}
}
System.out.println(sum);
}
到这里,整体的框架结构就OK了,其他就是具体的实现了,也就是最下面的四个Func函数。最后就是调用的时候,把这个函数传进去就行
common(integerList, Main::oddFunc1, Main::evenFunc1);
common(integerList, Main::oddFunc2, Main::evenFunc2);