java 更有效的方法来检查一个值是否包含在数组中?

vwhgwdsa  于 2022-12-21  发布在  Java
关注(0)|答案(3)|浏览(147)

写一个需要做很多比较的游戏,它很滞后。我正在试着加速它,这段代码每一帧都要运行数千次,对于不同的xy和z值。有没有更好的方法来检查数组中xy和z的值是否有效?(java)
第一个月
我试过检查blocksArr[x][y][z]!是否为null,也试过检查blocksArr[x][y][z]!是否为undefined,但都没有给予结果。

ntjbwcob

ntjbwcob1#

你所做的是边界检查,以确保索引xyzblocksArr[][][]数组中的有效索引,在C中,这是必要的,因为C允许你到数组之外。
然而,Java在每次访问数组时都会进行边界检查,所以你要手动进行边界检查,然后再进行一次检查,再加上Java在二维空间进行检查,最后Java在三维空间进行检查。
您真正需要做的只是访问数组,让Java进行边界检查,如果任何索引超出边界,则捕获异常。

boolean value;

    try
    {
        value = blocksArr[x][y][z];
    }
    catch (ArrayIndexOutOfBoundsException e )
    {
        value = false;
    }

设置try/catch块会有一些开销,但总体上应该会更快。

omvjsjqw

omvjsjqw2#

一般来说,在u已知为正的情况下,计算t >= 0 && t < u的最有效方法是使用Integer.compareUnsigned(t, u) < 0比较tu的无符号值。

if (Integer.compareUnsigned(x, blocksArr.length) < 0 &&
    Integer.compareUnsigned(y, blocksArr[x].length) < 0 &&
    Integer.compareUnsigned(z, blocksArr[x][y].length) < 0 &&
    blocksArr[x][y][z])

但是,我认为您将blocksArr表示为三维数组的效率非常低,并且会导致大量间接操作,这极大地阻碍了潜在的性能。一个更合理的方法是将其表示为单个数组,并将长度、宽度和高度分别存储。这将导致您的代码看起来像这样:

if (Integer.compareUnsigned(x, length) < 0 &&
    Integer.compareUnsigned(y, width) < 0 &&
    Integer.compareUnsigned(z, height) < 0 &&
    blocksArr[x * (width * height) + y * height + z])

然而,这限制了你的块大约20亿个元素,为了克服这个限制,你需要求助于内存访问API,它目前正在预览中。它有一个重要的优势,它允许内存块的分配和释放是确定的,这是太大的内存块更可取的。使用内存段来表示blocksArr,你的代码将成为:

if (Long.compareUnsigned(x, length) &&
    Long.compareUnsigned(y, width) &&
    Long.compareUnsigned(z, height) &&
    blocksArr.get(ValueLayout.JAVA_BOOLEAN, x * (width * height) + y * height + z))

此外,由于blocksArr是一个布尔值块,将其打包,使每个元素仅占1位,将大大改善内存消耗和缓存压力,现在的检查可以表示为:

long index = x * (width * height) + y * height + z;
long byteIndex = index >>> 3;
int shift = (int)(index & 7);
if (Long.compareUnsigned(x, length) &&
    Long.compareUnsigned(y, width) &&
    Long.compareUnsigned(z, height) &&
    blocksArr.get(ValueLayout.JAVA_BYTE, byteIndex) & (1 << shift) != 0)
blmhpbnm

blmhpbnm3#

我不懂java,但总的来说,我希望下面的代码至少和java一样快,可能更快。你的编译器可能会做类似的事情,所以它可能不会更快。你可以把“If”语句分开,这样它会做更少的查找。对不起,我必须把它写成c代码。你可以理解这个想法,然后翻译成java。

if (x >= 0 && y >= 0 && z >= 0 && x < blocksArr.length) {
  if (y < blocksArr[x].length && z < blocksArr[x][y].length && blocksArr[x][y][z]) {
    .....
  }
}

假设user16320675关于求值顺序是正确的,你可以使用一个if语句,我不知道java编译器是如何工作的。

if (x >= 0 && y >= 0 && z >= 0 && x < blocksArr.length && y < blocksArr[x].length && z < blocksArr[x][y].length && blocksArr[x][y][z]) .....

相关问题