Java 迭代二维数组的偏移量

Java 迭代二维数组的偏移量,java,performance,for-loop,if-statement,Java,Performance,For Loop,If Statement,我想在2D数组中迭代单元格的邻域。因此,我使用: for (int xOffset = -1; xOffset <= 1; xOffset++) { for (int yOffset = -1; yOffset <= 1; yOffset++) { if (xOffset == 0 && yOffset == 0) { continue; } //My Code } } 对于(i

我想在2D数组中迭代单元格的邻域。因此,我使用:

for (int xOffset = -1; xOffset <= 1; xOffset++) {
    for (int yOffset = -1; yOffset <= 1; yOffset++) {
        if (xOffset == 0 && yOffset == 0) {
            continue;
        }
        //My Code
    }
}

对于(int xOffset=-1;xOffset我通常使用以下方法:

int dirs[][] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};

for (int dir[] : dirs) {
    int xOffset = dir[0];
    int yOffset = dir[1];
    // my code
}

我通常使用以下方法:

int dirs[][] = {{-1, -1}, {-1, 0}, {-1, 1}, {0, -1}, {0, 1}, {1, -1}, {1, 0}, {1, 1}};

for (int dir[] : dirs) {
    int xOffset = dir[0];
    int yOffset = dir[1];
    // my code
}

尚未对其进行测试,但以下内容基于@Zefick的答案,应该更有效:

int dirs[] = { -1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1 };

for (int i = 0; i < dirs.length; i += 2) {
    int xOffset = dirs[i];
    int yOffset = dirs[i + 1];
    // my code
}       
intdirs[]={-1,-1,-1,0,-1,1,0,1,1,1,-1,1,0,1,1};
对于(int i=0;i
尚未对其进行测试,但以下内容基于@Zefick的答案,应该更有效:

int dirs[] = { -1, -1, -1, 0, -1, 1, 0, -1, 0, 1, 1, -1, 1, 0, 1, 1 };

for (int i = 0; i < dirs.length; i += 2) {
    int xOffset = dirs[i];
    int yOffset = dirs[i + 1];
    // my code
}       
intdirs[]={-1,-1,-1,0,-1,1,0,1,1,1,-1,1,0,1,1};
对于(int i=0;i
我使用各种解决方案运行了一个JMH基准测试。我总是在黑洞中使用2个偏移量索引。以下是结果:

Benchmark                                  Mode  Cnt         Score         Error  Units
Offset2DBenchmark.doubleLoopWithIf        thrpt    3  35425373,827 ± 4242716,439  ops/s
Offset2DBenchmark.loopOverFlatIndex       thrpt    3  35929636,197 ±  935681,592  ops/s
Offset2DBenchmark.loopOverIndex           thrpt    3  31438051,279 ± 3286314,668  ops/s
Offset2DBenchmark.unrolledLoop            thrpt    3  40495297,238 ± 6423961,118  ops/s
Offset2DBenchmark.unrolledLoopWithLambda  thrpt    3  27526581,417 ± 1712524,060  ops/s


doubleLoopWithIf       = Nested Loops with If to filter 0,0 (TheSorm)
loopOverFlatIndex      = Single loop with flattend indizes (Oleg)
loopOverIndex          = Single Loop with 2d indizes (Zefick)
unrolledLoop           = Completely Unrolled Loop
unrolledLoopWithLambda = Unrolled Loop consuming a Bifunction<Integer, Integer>
使用

你应该能够完全避免做乘法运算


(这是我第一次用JMH运行基准测试,所以请告诉我我是否使用了完全错误的基准测试…

我用各种解决方案运行了一个JMH基准测试。我总是在黑洞中使用2个偏移量。以下是结果:

Benchmark                                  Mode  Cnt         Score         Error  Units
Offset2DBenchmark.doubleLoopWithIf        thrpt    3  35425373,827 ± 4242716,439  ops/s
Offset2DBenchmark.loopOverFlatIndex       thrpt    3  35929636,197 ±  935681,592  ops/s
Offset2DBenchmark.loopOverIndex           thrpt    3  31438051,279 ± 3286314,668  ops/s
Offset2DBenchmark.unrolledLoop            thrpt    3  40495297,238 ± 6423961,118  ops/s
Offset2DBenchmark.unrolledLoopWithLambda  thrpt    3  27526581,417 ± 1712524,060  ops/s


doubleLoopWithIf       = Nested Loops with If to filter 0,0 (TheSorm)
loopOverFlatIndex      = Single loop with flattend indizes (Oleg)
loopOverIndex          = Single Loop with 2d indizes (Zefick)
unrolledLoop           = Completely Unrolled Loop
unrolledLoopWithLambda = Unrolled Loop consuming a Bifunction<Integer, Integer>
使用

你应该能够完全避免做乘法运算



(这是我第一次使用JMH运行基准测试,所以请告诉我是否使用了完全错误的基准测试…)

您认为最具可读性和可维护性的解决方案是什么?这里是否有实际的性能问题需要解决?是的,这是一个性能问题,我会尽我所能优化。这是在数百万对象的更新循环中运行的。那么,使用当前解决方案是否有实际的性能问题?它是关于在每一滴答都被使用上百万次的事物中找到几纳米或几毫秒,我理解,但OP是在问一个可能存在也可能不存在的问题。也许这已经是最快的解决方案。他们似乎已经有了一些不同的解决方案,所以我对OP的挑战就是让你的马比赛。你认为这是什么他是最具可读性和可维护性的解决方案?这里有实际的性能问题需要解决吗?是的,这是一个性能问题,我会尽我所能优化。这是在数百万对象的更新循环中运行的。所以,同样,使用您当前的解决方案是否有实际的性能问题?这是关于找到几个nanor毫秒,在每次滴答声中被使用数百万次。我理解,但OP是在询问一个可能存在或可能不存在的问题。也许这已经是最快的解决方案。他们似乎已经有了一些不同的解决方案,所以我对OP的挑战就是让你的马比赛。好的,我会接受xOffset,yOffset声明o在循环外部,但有一件好事谢谢:)@将由JIT编译器(或普通编译器)优化的表单,不需要这样做。@Oleg哦,好吧,酷,我从来都不是舒尔编译器做什么,所以我尝试自己做类似的事情来获得舒尔:D@TheSorm根据这个答案,关于StackOverflow有很多问题:在循环内声明会更快!一般来说,我建议专注于编写可读代码,只有在发现问题后才进行微优化。@Zefick我发现,即使我将dirs作为最终全局变量,您的实现速度也只有我的一半。但是谢谢你的帮助:)好的,我会把xOffset,yOffset声明放在循环之外,但是有一件好事谢谢:)@这个表单将由JIT编译器(或者只是普通的编译器)优化,不需要这样做。@Oleg哦,好吧,酷,我从来都不是舒尔编译器做什么,所以我尝试自己做类似的事情来获得舒尔:D@TheSorm根据这个答案,关于StackOverflow有很多问题:在循环内声明会更快!一般来说,我建议专注于编写可读代码,只有在发现问题后才进行微优化。@Zefick我发现,即使我将dirs作为最终全局变量,您的实现速度也只有我的一半。但是谢谢你的帮助:)哇,谢谢你所做的一切:)对于展开的循环,你的意思是只有一个循环,不是吗?对于展开的循环,我的意思是,你根本不用循环。复制并粘贴代码,直到有8个副本。然后硬编码xOffset和yOffset的值。应该没问题,因为你在追求表演。就可维护性而言,这是最丑陋的。干得好,也许可以通过增加热身和热身的次数来减少误差偏差,但即使这样,结果还是有意义的,并且表明这里没有多少可以优化的。哇,谢谢你所做的所有工作:)对于展开的循环,你的意思是只有一个循环,不是吗?对于展开的循环,我的意思是,你根本不使用循环。复制并粘贴代码,直到有8个副本。然后硬编码xOffset和yOffset的值。应该没问题,因为你在追求表演。就可维护性而言,它是最丑陋的。做得好,可能通过增加热身和热身次数来减少误差偏差,但即使是这样,结果还是有意义的,并且表明这里没有多少可以优化的。