不使用嵌套循环遍历3D空间的实现方法:代码优化与效率探讨
不使用嵌套循环实现3D区块遍历查找ANCIENT_DEBRIS
当然有不使用嵌套循环的实现方式,下面列出几种常见方案,并分析它们的简洁性和执行效率:
一、单循环+坐标线性转换
把三维坐标转换成一维索引,通过数学计算反推出x、y、z,用单个循环完成遍历:
int totalBlocks = (Y_LEVEL_STOP - Y_LEVEL_START + 1) * CHUNK_SIDE * CHUNK_SIDE; for (int i = 0; i < totalBlocks; i++) { // 从线性索引反推三维坐标 int y = Y_LEVEL_START + (i / (CHUNK_SIDE * CHUNK_SIDE)); int remaining = i % (CHUNK_SIDE * CHUNK_SIDE); int z = remaining / CHUNK_SIDE; int x = remaining % CHUNK_SIDE; if (chunk.getBlock(x, y, z).getType() == ANCIENT_DEBRIS) { report.debrisFoundAt(x, y, z); } }
二、Java 8+流API扁平化遍历
利用流的flatMap操作把三维维度的流扁平化,避免显式嵌套循环:
IntStream.rangeClosed(Y_LEVEL_START, Y_LEVEL_STOP) .boxed() .flatMap(y -> IntStream.range(0, CHUNK_SIDE) .boxed() .flatMap(z -> IntStream.range(0, CHUNK_SIDE) .mapToObj(x -> new int[]{x, y, z}))) .forEach(coords -> { int x = coords[0]; int y = coords[1]; int z = coords[2]; if (chunk.getBlock(x, y, z).getType() == ANCIENT_DEBRIS) { report.debrisFoundAt(x, y, z); } });
三、自定义迭代器封装遍历逻辑
把三维遍历的逻辑封装到自定义迭代器中,业务代码只需要简单遍历迭代器:
// 自定义区块块坐标迭代器 class BlockIterator implements Iterator<int[]> { private final int yStart; private final int yStop; private final int chunkSide; private int currentY; private int currentZ; private int currentX; public BlockIterator(int yStart, int yStop, int chunkSide) { this.yStart = yStart; this.yStop = yStop; this.chunkSide = chunkSide; this.currentY = yStart; this.currentZ = 0; this.currentX = 0; } @Override public boolean hasNext() { return currentY <= yStop; } @Override public int[] next() { int[] coords = {currentX, currentY, currentZ}; // 更新坐标,逻辑和嵌套循环一致 currentX++; if (currentX >= chunkSide) { currentX = 0; currentZ++; if (currentZ >= chunkSide) { currentZ = 0; currentY++; } } return coords; } } // 业务代码中使用 BlockIterator blockIterator = new BlockIterator(Y_LEVEL_START, Y_LEVEL_STOP, CHUNK_SIDE); while (blockIterator.hasNext()) { int[] coords = blockIterator.next(); int x = coords[0]; int y = coords[1]; int z = coords[2]; if (chunk.getBlock(x, y, z).getType() == ANCIENT_DEBRIS) { report.debrisFoundAt(x, y, z); } }
简洁性与执行效率分析
简洁性
- 单循环方式:代码行数和原嵌套循环相近,没有嵌套结构,但需要理解坐标转换的数学逻辑,对新手门槛略高,整体逻辑清晰。
- 流API方式:没有显式循环嵌套,采用声明式写法,符合函数式编程风格,但为了传递坐标需要包装成数组,额外增加了一点复杂度,可读性因人而异。
- 自定义迭代器:把遍历逻辑完全封装,业务代码非常简洁,还能复用遍历逻辑,但需要额外编写迭代器类,增加了整体代码量。
执行效率
- 单循环方式:和原嵌套循环效率几乎一致,本质都是遍历所有块,坐标计算的开销可以忽略,JVM会做优化,性能差异微乎其微。
- 流API方式:效率略低于传统循环,流的扁平化操作、对象包装会带来额外的内存和计算开销,区块越大,这种损耗越明显,但非极致性能场景下可以接受。
- 自定义迭代器:和原嵌套循环效率接近,迭代器内的坐标更新逻辑和嵌套循环的条件判断本质相同,没有额外性能损耗。
内容的提问来源于stack exchange,提问作者VoidPointer
相关产品推荐
相关产品推荐

