我最近开始学习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。另外,由于局限性,我不想使用常规数组。
答案 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
等索引数据结构缩减为线性。