【问题标题】:What is the best way to reuse a for-loop?重用 for 循环的最佳方法是什么?
【发布时间】:2020-07-06 10:52:11
【问题描述】:

我目前正在开发一个(将)允许您对其执行操作的 Matrix 类。但是,因为我使用二维数组来表示类中的矩阵,所以我经常发现自己使用以下循环(对所有元素执行操作):

    for (int y = 0; y < this.matrix.length; y++) {
        for (int x = 0; x < this.matrix[0].length; x++) {
            // do something
        }
    }

什么是重用这个循环的好方法,但让它在循环内执行不同的代码?

我已经考虑过功能接口,但还没有完全弄清楚。

【问题讨论】:

  • 应该是this.matrix[y]而不是this.matrix[0],否则这没什么问题
  • 功能接口可以解决这个问题,但很可能会减慢处理速度。

标签: java for-loop functional-interface


【解决方案1】:

如果你在方法中有这个

void iterateMatrix(int[][] matrix) {
    for (int y = 0; y < matrix.length; y++) {
        for (int x = 0; x < matrix[0].length; x++) {
            // do something
        }
    }
}

你可以为“做某事”定义一个功能接口

interface MatrixVisitor {
    void accept(int x, int y, int value);
}

它是一个“函数式接口”,因为它只包含一个方法;你可以用@FunctionInterface标记它,但这只是一个标记,没有必要。

你可以通过

void iterateMatrix(int[][] matrix, MatrixVisitor consumer) {
    for (int y = 0; y < matrix.length; y++) {
        for (int x = 0; x < matrix[0].length; x++) {
            consumer.accept(x, y, matrix[x][y]);
        }
    }
}

它是一个函数式接口的效果是你可以使用 lambda 来“实现”它,比如

iterateMatrix(this.matrix, (x, y, value) -> System.out.printf("value at %d/%d: %d%n", x, y, value));

问题仍然是这是否是“最好的方式”,这是一个相当微不足道的循环,所以我不知道重复使用它是否值得。

【讨论】:

  • X 和 Y 本身似乎并没有那么有用。大概你也关心 X,Y 的值。
  • @michael 你是对的,并没有真正考虑实际语义并假设这些是值。
  • 别害羞,指出它为什么叫 MatrixVisitor。 OP,这是一种“访客”设计模式,一种特殊的“策略”模式。在 Wikipedia 中查看它们以了解它们的理论用途。关键是,您可以切换访问者以更改循环的语义,同时保持遍历相同,即。重复使用循环。
  • 您应该将@FunctionalInterface 添加到MatrixVisitor。 --- 您应该修复问题中的潜在问题并使用matrix[y].length 而不是matrix[0].length,因此代码也适用于锯齿状数组,即使它不符合名称的“矩阵”部分。
  • @Andreas 是的,对于操作代码,我会有一个 Matrix 类,但这个答案的重点是解释什么是功能接口。我故意省略了 @FunctionalInterface 注释以明确表明它不是必需的。
【解决方案2】:

你说你不熟悉函数式接口,所以这里有一个使用普通类的替代方法,它允许你使用 Java 的 for-each 循环。

我假设您的矩阵值是双精度值,但如果不是,则将您使用的任何类型的双精度值切换出去。

static class MatrixElement {
    private final int x;
    private final int y;
    private final double value;

    // ctor, getters
}

static Iterable<MatrixElement> matrixIterable(double[][] matrix) {
    final List<MatrixElement> elements = new ArrayList<>();
    for (int y = 0; y < matrix.length; y++) {
        for (int x = 0; x < matrix[y].length; x++) {              
            elements.add(new MatrixElement(x, y, matrix[x][y]));
        }
    }
    return elements;
}

示例用法:

double[][] matrix = {{1.1, 2.2}, {3.3, 4.4}};
for (MatrixElement element : matrixIterable(matrix)) {
    System.out.println("(" + element.getX() + ", " + element.getY() + ") " + element.getValue());
}

打印

(0, 0) 1.1
(1, 0) 3.3
(0, 1) 2.2
(1, 1) 4.4

【讨论】:

  • 谢谢!绝对是我会玩的东西!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-09-06
  • 1970-01-01
  • 2017-02-20
  • 2019-11-20
  • 1970-01-01
  • 2017-07-13
  • 1970-01-01
相关资源
最近更新 更多