Java - 避免矩阵迭代中的代码重复

时间:2014-05-04 19:52:09

标签: java refactoring code-duplication

假设我有一个int [size] [size]矩阵。我想像这样迭代它:

01 02 03 04
08 07 06 05
09 10 11 12
16 15 14 13

我真的要说:

for (int y=0; y<size; y++) {
    int startIndex, endIndex, increment;
    boolean lessThan;
    if (y%2 == 0) {
        startIndex = 0;
        endIndex = size;
        lessThan = true;
        increment = 1;
    }
    else {
        startIndex = size-1;
        endIndex = -1;
        lessThan = false;
        increment = -1;
    }
    for (int x=startIndex; lessThan ? x<endIndex : x>endIndex; x+=increment) {
        // Process element
    }
}

避免这样做:

for (int y=0; y<size; y++) {
    if (y%2 == 0) {
        for (int x=0; x<size; x++) {
            // Process element
        }
    }
    else {
        for (int x=size-1; x>-1; x--) {
            // Process element
        }
    }
}

哪个更好但重复代码。有没有更好的方法来构建它?

4 个答案:

答案 0 :(得分:1)

创建一个interface来抽象处理元素的逻辑:

interface ElementConsumer {
    void consume(int element);
}

然后在循环中使用这个抽象:

void iterateMatrix(final int[][] matrix, final ElementConsumer consumer) {
    for (int y = 0; y < size; y++) {
        if (y % 2 == 0) {
            for (int x = 0; x < size; x++) {
                consumer.consume(matrix[x][y]);
            }
        } else {
            for (int x = size - 1; x > -1; x--) {
                consumer.consume(matrix[x][y]);
            }
        }
    }
}

使用这种方法:

iterateMatrix(matrix, new ElementConsumer() {
    @Override
    public void consume(int element) {
        //do stuff
    }
});

在Java 8中,您可以使用现有的IntConsumerLongConsumer功能接口和lambda:

iterateMatrix(matrix, element -> /*doStuff*/);

答案 1 :(得分:1)

迭代矩阵的另一种方法:

for (int num = 0; num < maxX*maxY; ++num) { // num - element number
    // calc element coordinates
    int y = num / maxX;
    int x = num % maxX;
    if (y % 2 == 1)
       x = maxX - x;
    int elem = matrix[x][y];
    // process element
}

答案 2 :(得分:1)

也可以这样完成..

package com.kvvssut.misc;

public class TraverseAlternately {

    public static void main(String[] args) {
        traverseAlternately(new int[][]{{1,2,3,4},{8,7,6,5},{9,10,11,12},{16,15,14,13}});
    }

    private static void traverseAlternately(int[][] inputs) {
        int rows = inputs.length;
        if (rows > 0) {
            int i = -1;
            int j = 0;

            int cols = inputs[j].length;        // assuming all rows have same no.s of values

            while (true) {
                while (++i < cols) {        // traverses till the end of first row
                    System.out.println(inputs[j][i]);
                }
                if (j < rows - 1) {     // if reaches the no.s of rows, loop breaks
                    j++;
                } else {
                    break;
                }

                while (--i >= 0) {          // traverses backward to the zeroth location
                    System.out.println(inputs[j][i]);
                }
                if (j < rows - 1) {     // if reaches the no.s of rows, loop breaks
                    j++;
                } else {
                    break;
                }
            }
        }
    }

}

答案 3 :(得分:0)

for (int y = 0; y < size; y++) {
    for (int x = (y%2 == 0 ? 0 : size - 1);
            (y%2 == 0 ? x < size : x >= 0);
            (y%2 == 0 ? x++ : x--)) {
        // Process element
    }
}