Shellbye.github.io icon indicating copy to clipboard operation
Shellbye.github.io copied to clipboard

Java 8 通过 FunctionalInterface 实现函数作为参数传递

Open Shellbye opened this issue 6 years ago • 0 comments

日常工作中,我们可能会遇到不少业务场景,他们的整体结构都是一样的,只是有一小部分有差别。我们把这样的场景抽象成以下的代码段

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;
    }

}

首先我们定义了针对奇数和偶数不同的处理方式的两个接口IntOddOperatorIntEvenOperator,并在其内部定义了具体的方法签名。

@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);

Shellbye avatar Mar 12 '19 11:03 Shellbye