在java中这两个数组之间是否有任何性能差异(可能与J2ME开发相关…):
String[][][] a = //for getting an entry by a[group][person][field]
{
{ // group A:
{"John", "Doe", "teacher", "New York"},
{"Donald", "Duck", "jinx", "Duckburg"},
// 10 or more further entries
},
{ // group B:
{"Barack", "Obama", "president", "Washington"},
// ...
}
};
String[][][] b = //for getting an entry by b[field][group][person]
{
{ // prenames:
{"John", "Donald", ...},
{"Barack", ...}
},
{ // surnames:
{"Doe", "Duck", ...},
{"Obama", ...}
},
{ // job:
{"teacher", "jinx", ...},
{"president", ...}
},
{ // city:
{"New York", "Duckburg", ...},
{"Washington", ...}
}
};
我猜第二个数组性能更好,因为它由更少的嵌套数组组成,而第一个数组每个人有一个数组!
谢谢你的回答!
更新:
一个更好的(现实的)例子是一个包含1000个x/y坐标的数组:
int[][] coordsA =
{
{0, 0},
{2, 7},
{8, 2},
{4, 2},
{-3, 15},
{1, 32},
// ...
};
int[][] coordsB =
{
{0, 2, 8, 4, -3, 1, ...}, // x values
{0, 7, 2, 2, 15, 32, ...} // y values
}
多年前,当我还在使用Fortran时,我们被告知要在多维数组上安排循环,这样第一个维度是迭代最快的,因为内存的排列方式,它会导致更少的页面错误。
然而,从那时起,我了解到,在Java中(几乎在所有事情中),如果你有性能问题,你应该测量所有提出的解决方案,直到你找到一个解决方案,你不再有性能问题。过早优化是万恶之源。如果您认为数组的数量将是一个问题,您是否测量过每个选项占用的内存量?您是否测量过特定操作所需的时间?
如果您没有性能问题,那么请使用最适合您需求的表示。
<insert usual knuth quote, etc. here - but I assume anyone here knows that already anyhow>
Java的问题是,每个数组级别被视为一个对象本身,也就是说,我们没有为我们的数组获得连续的内存区域(好吧,GC可以帮助一点)
这有几个作用:
- 更差的缓存位置
- 每个数组级别的附加边界检查
- 访问一个元素所需的额外内存访问
不是很好(即在最坏的情况下,我们可能会得到2*索引级别的内存访问,而不是对一个元素进行一次内存访问),所以如果你需要高效的数组,通常的解决方案是只创建一个大数组并自己进行索引。这避免了所有这些问题,代价是需要一些简单的辅助方法(这非常简单,特别是如果所有子数组具有相同的大小)。
但是的性能提升很大程度上取决于您的访问方案。如果你想比较你的帖子中给出的两种不同的变体,它可能不会那么重要(即,如果你正确地排序你的数组,你在C或co中获得的相同收益无处可去)。在子数组中顺序访问它们仍然可以提供更好的缓存局部性。