【问题标题】:How do I efficiently iterate through a big list?如何有效地遍历一个大列表?
【发布时间】:2018-12-22 16:43:41
【问题描述】:

我想制作一个类似于 Minecraft 的开放世界 2D 游戏,并将世界加载到块(就像 MC)中,大小为 16x16 块(总共 256 个块)。但是我通过迭代 256 次发现,用这样的代码完全迭代需要将近 20ms:

long time = System.nanoTime();
for(int i = 0; i < 16*16; i++)
{
    System.out.println(i);
}
System.out.println(System.nanoTime() - time);

因为我不仅要打印数字,还要获取一个块,获取它的纹理并将该纹理绘制到框架上,我担心迭代可能需要更长的时间。也许我只是夸大了一点,但有没有办法更快地迭代?

【问题讨论】:

  • 除非你转向多线程
  • 如果你真的想访问所有这 256 个区块,你肯定需要访问所有这些区块。唯一可能提高遍历速度的是在并行线程中访问它们。但这听起来不像你的用例。
  • 我不太确定迭代的原因,但是如果您正在搜索某些东西并且您知道坐标,也许可以查看不同类型的搜索,不是线性的,因为这不是最高效,即 0 一直到 255 不是很有效,将其拆分可能更有效。如果它只是初始加载,那么您可以在用户看到它之前完成所有操作,然后显示它。如果是用于操作特定坐标,那么多维数组可能会适合。如果您必须参考 0-255 的坐标,那么您将能够操纵这个参考
  • print 不是一个快速操作,那么当您的 real 代码根本不会进行任何打印时,为什么要对 256 个值的打印进行性能测试。这就像说您认为哈雷车很慢,因为您在踏板车上进行了试驾。这是一个毫无意义的测试。扔掉那个代码,做你真正想做的事,然后分析那个代码,如果你确实有它的性能问题。

标签: java arrays iteration


【解决方案1】:

这不是需要 20 毫秒的迭代,而是 println();。 以下会更快:

long time = System.nanoTime();
StringBuilder sb = new StringBuilder();
for(int i = 0; i < 16*16; i++)
{
    sb.append(i + System.getProperty("line.separator"));
}
System.out.println(sb);
System.out.println(System.nanoTime() - time);

【讨论】:

    【解决方案2】:

    因此,首先,请考虑到 256 的列表通常不被认为具有很大的大小。

    您的代码消耗时间的主要不是遍历列表,而是使用System.out.println()。打印到控制台(或任何 I/O 操作)往往比其他指令花费更长的时间。

    当我在本地尝试你的代码时,我得到大约 6 毫秒,但如果我这样做:

        long secondStart = System.nanoTime();
        StringBuffer stringBuffer = new StringBuffer();
        for(int i = 0; i < 16*16; i++)
        {
            stringBuffer.append(i);
            stringBuffer.append("\n");
        }
        System.out.println(stringBuffer);
        System.out.println(System.nanoTime() - secondStart);
    

    我得到 0.5 毫秒。

    如果该方法不适合您的需求,那么您需要像其他 cmets 所说的那样,考虑并行遍历列表的不同部分,可能会转向不同类型的遍历,甚至是不同类型的结构。

    希望这会有所帮助。

    【讨论】:

      【解决方案3】:

      你应该问问自己是否真的需要做所有这些工作。例如,您是否需要绘制相机看不到的东西?当然不是,因此排除该块中位于相机矩形之外的每个块。

      过滤掉看不见的块意味着一些开销,但与在每次渲染更新时绘制块中的每个块相比,它通常是值得的,因为绘制东西是一项相当繁重的操作。

      如果您只想加快遍历速度,您可以生成并行遍历块的线程或购买更好的硬件。但最好从如何以更少的工作量获得相同结果的问题开始。

      另一方面,您的计算机应该能够毫无问题地绘制 256 个纹理,尤其是在 gpu 上完成时。因此,在进行过早优化之前可能会进行一些测试。

      附言。实际上,您要优化的并不是遍历本身,而是每次迭代中完成的工作。只需迭代 256 次就会非常快。

      【讨论】:

        猜你喜欢
        • 2022-01-23
        • 1970-01-01
        • 2013-09-13
        • 1970-01-01
        • 2022-06-18
        • 1970-01-01
        • 1970-01-01
        • 2022-01-24
        • 2012-08-21
        相关资源
        最近更新 更多