Applying DRY when looping with a small change in each function

Kshitij Bajracharya :

Suppose I have the following piece of code that finds the sums and products of an array of array of integers.

public class Foo {

    public static void main(String[] args) {
        int[][] numberLists = new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};

        int[] sums = getListOfSums(numberLists);
        int[] products = getListOfProducts(numberLists);

        print(sums);
        System.out.println("----");
        print(products);
    }

    private static int[] getListOfSums(int[][] numberLists) {
        int[] sums = new int[3];
        for (int i = 0; i < 3; i++) {
            sums[i] = add(numberLists[i]);
        }
        return sums;
    }

    private static int[] getListOfProducts(int[][] numberLists) {
        int[] products = new int[3];
        for (int i = 0; i < 3; i++) {
            products[i] = multiply(numberLists[i]);
        }
        return products;
    }

    private static int add(int[] numbers) {
        int sum = 0;
        for (int number : numbers) {
            sum += number;
        }
        return sum;
    }

    private static int multiply(int[] numbers) {
        int product = 1;
        for (int number : numbers) {
            product *= number;
        }
        return product;
    }

    private static void print(int[] results) {
        for (int result : results) {
            System.out.println(result);
        }
    }

}

The output is:

6
15
24
----
6
120
504

In the functions, getListOfSums and getListOfProducts, every line is the same except the function being called, i.e. add and multiply respectively. Is there a better way to write this so that the code is not repeated? Is there any way to pass functions as arguments?

The code doesn't look terrible in this simple problem, but when the problem becomes complex with 10+ lines inside the for loop and multiple functions using similar structure, then the code doesn't look clean. Is there any way to overcome this mess?

Eran :

You can write a single method that accepts a Function<int[],Integer> and applies this function to the input arrays:

private static int[] getListOfOperator(int[][] numberLists, Function<int[],Integer> operator) {
    int[] products = new int[3];
    for (int i = 0; i < 3; i++) {
        products[i] = operator.apply(numberLists[i]);
    }
    return products;
}

And the Function implementations can look like this:

Function<int[],Integer> sum = Foo::add;
Function<int[],Integer> product = Foo::multiply;

Your main will become:

public static void main(String[] args) {
    int[][] numberLists = new int[][] {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
    int[] sums = getListOfOperator(numberLists,Foo::add);
    int[] products = getListOfOperator(numberLists,Foo::multiply);
    print(sums);
    System.out.println("----");
    print(products);
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=78370&siteId=1