java - 循环内的逻辑?或者更确切地说是两个独立的几乎相同的循环?

原文 标签 java loops if-statement convention

注意:我的印象是您想避免循环内的逻辑语句。我认为这部分是因为编译器如何优化迭代行为可预测的任何循环。虽然我几乎可以肯定我以前听过这个,而且很长一段时间我都认为这是一种惯例。遗憾的是,我找不到任何好的引用资料。如果这是真的,但是由于“DRY”原则(不要重复自己),存在一些相互矛盾的情况。

PRETEXT:假设你有一个相当大的数据集,比如我在这个例子中使用的一个多维数组。此外假设您需要遍历每个条目并对所有或部分元素执行一些操作,并且您需要能够选择要执行的一个或另一个操作。这需要创建两个方法,其中 90%-99% 的代码在两者之间是相同的,而只有操作符或方法调用不同。如果这是 C++,我会想提供一个指向循环函数的函数指针,尽管我不知道这是否也最好避免。

问题:最好使用逻辑语句并且只有一个循环还是两个几乎相同的方法?

示例:我提供了一些示例来展示“双胞胎”方法解决方案的冗余程度:

// This method is provided for completeness of the example
// and to provide some clue as to what boolean parameter and logic statement 
// I could alternatively have implemented within the loop method instead of external to it.
public int[][] addOrSubtractArrays(int[][] a, int[][] b, boolean useAdd){
    if(a == null || b == null || a.length != b.length || a.length < 1 || a[0].length != b.length)
        return null;
    return useAdd ? add(a, b) : subtract(a, b);
}

private int[][] add(int[][] a, int[][] b){
    int h = a.length;
    int w = a[0].length;
    int[][] c = new int[h][w];
    for(int y = 0; y < h; y++){
        for(int x = 0; x < w; x++){
            c[y][x] = a[y][x] + b[y][x];
        }
    }
    return c;
}

private int[][] subtract(int[][] a, int[][] b){
    int h = a.length;
    int w = a[0].length;
    int[][] c = new int[h][w];
    for(int y = 0; y < h; y++){
        for(int x = 0; x < w; x++){
            c[y][x] = a[y][x] - b[y][x];
        }
    }
    return c;
}

示例 2:(显而易见的?)替代方案
private int[][] addOrSubtract(int[][] a, int[][] b, boolean useAdd){
    if(a == null || b == null || a.length != b.length || a.length < 1 || a[0].length != b.length)
        return null;
    int h = a.length;
    int w = a[0].length;
    int[][] c = new int[h][w];
    for(int y = 0; y < h; y++){
        for(int x = 0; x < w; x++){
            if(useAdd)
                c[y][x] = a[y][x] + b[y][x];
            else
                c[y][x] = a[y][x] - b[y][x];
        }
    }
    return c;
}

我很想制作一些包含整个循环结构的通用方法来避免(几乎)重复代码。但是,如果“我所听到的”有一些合理的上下文,据我所知,最好避免这种情况。

最佳答案

addOrSubtract 不好。其他形式的算术怎么样,比如乘法?您可以公开一个 multiplyOrDivide ,但是如果有时间选择应该是 addOrMultiply 呢?不能很好地扩展。

您应该拥有一种方法,该方法允许客户端指定要执行的操作:

public int[][] calculate(int[][] first, int[][] second, Operation operation) {
    if(firstArray == null || secondArray == null || firstArray.length != secondArray.length || firstArray.length < 1 || firstArray[0].length != secondArray.length)
        throw new IllegalArgumentException("Arrays can't be null and must be of equal length.");

    int height = firstArray.length;
    int width = firstArray[0].length;
    int[][] result = new int[height][width];
    for(int y = 0; y < height; y++){
        for(int x = 0; x < width; x++){
            result[y][x] = operation.performOn(firstArray[y][x], secondArray[y][x]);
        }
    }
}

您现在可以根据需要添加新操作:
enum Operation {
    ADD {
        @Override
        public void performOn(int firstValue, int secondValue) {
            return firstValue + secondValue;
        }
    },
    SUBTRACT {
        //...
    };

    public abstract int performOn(int firstValue, int secondValue);
}

如果您觉得以这种方式覆盖会使缩放过于冗长,您可以通过将逻辑委托(delegate)给回调函数来利用策略模式:
enum Operation { //could/should implement IOperation
    ADD((a, b) -> a + b),
    SUBTRACT((a, b) -> a - b);

    private IOperation operation;

    Operation(IOperation operation) {
        this.operation = operation;
    }

    public final int performOn(int firstValue, int secondValue) {
        return operation.performOn(firstValue, secondValue);
    }
}

interface IOperation {
    int performOn(int firstValue, int secondValue);
}

客户端现在可以使用您的函数,如下所示:
calculate(firstArray, secondArray, Operation.ADD);

我选择创建一个新的函数式接口(interface)而不是使用 BiFunction 的原因是为了避免自动装箱。性能似乎是你的一个担忧,自动装箱会极大地影响性能,尤其是当你强烈地执行此操作时。无论是来自大尺寸的数组,还是需要在较短的时间范围内连续调用 addOrSubtract,最好避免这种陷阱。
IllegalArgumentException 允许程序用描述性消息“炸毁”。您返回了 null ,这意味着使用此方法的任何人都需要执行空检查(杂乱无章、代码异味、 billion dollar mistake ),否则他们可能会遇到没有描述性消息的 NullPointerException

关于java - 循环内的逻辑?或者更确切地说是两个独立的几乎相同的循环?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40758204/

相关文章:

java - 如何测试.jar版本?

java - 找出是C的最小整数?

java - Java + Regex:匹配来自定制集中的字符,这些字符之前没有相同的字符

javascript - 将多维数组中的所有整数相加 javascript

c - C中使用数组的for循环

与if语句的Javascript,元素的改变颜色,在点击

java - 如何在Java中激活窗口?

mysql - 基于CURRENT_TIME的MYSQL简单IF语句

if-statement - 为什么在 "if"语句中使用语句?

c - 无法计算无限循环情况