在ArrayList中查找Point的邻居

时间:2012-11-22 11:12:11

标签: java list arraylist iteration

我最近开始学习Java,虽然做一个“Conway's Game of Life”风格的程序是一件好事。一切正常,但我在这部分遇到了一些严重的性能问题:

static List<Point> coordList = new ArrayList<Point>();

public int neighbors(int x, int y){

    int n = 0;

    Point[] tempArray = { new Point(x-1, y-1), new Point(x, y-1), new Point(x+1, y-1), 
                          new Point(x-1, y  ),                    new Point(x+1, y  ),
                          new Point(x-1, y+1), new Point(x, y+1), new Point(x+1, y+1)};
    for (Point p : tempArray) {
        if (coordList.contains(p))
            n++;
        }

    return n;
}

在迭代用 Points 填充的ArrayList coordList 并检查每个元素有多少邻居时,使用该方法。当列表大小达到大约10000 时,每个周期大约需要1秒,而对于20000个点,则需要7秒。

我的问题是,有什么更有效的方法呢?我知道还有其他几个这样的程序,源代码也可以看,但我不能尽我所能,因为项目的重点是我学习Java。另外,由于局限性,我不想使用常规数组。

3 个答案:

答案 0 :(得分:1)

如果您的积分是唯一的,则可以将其存储在a HashSet而不是ArrayList。然后,contains方法将成为当前设置中的O(1)操作与O(n)的操作。这应该会显着加快这一部分。

除了声明之外,您的代码应保持基本不变,因为两者都实现了Collection接口,除非您调用特定于列表的方法,例如get(i)

答案 1 :(得分:1)

在性能方面,我认为最好的办法是使用一个表示网格的简单数字(有效布尔)数组。由于这是一个学习练习,我将从一个简单的单元素单元格数组开始,然后可能会将八个相邻单元格打包成一个字节。

“限制”是什么意思并不完全清楚。

以下是一些有趣的指示:Optimizing Conway's 'Game of Life'

答案 2 :(得分:1)

您当前的代码以二次方式缩放O(n^2)。你只给了部分程序。如果您查看整个程序,将会有一个调用neighbors()的循环,您将看到neighbors()被调用n次。此外,操作contains()在n中是线性的,因此时间与其乘积n*n成比例。

二次缩放是一个常见问题,但通常可以通过使用HashSet等索引数据结构缩减为线性。