You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

不使用嵌套循环遍历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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.22 14:48:17