我想在[400] [400]数组中存储/访问和查找一些int和double值。 以前的代码执行速度很慢。我听说一个字节数组没有进展,我 需要int和double值。 为什么在android中需要这么长时间?这些是非常原始的数据类型。 我怎样才能以有效的方式做到这一点?
public static double[][]mat_cost = new double[400][400];
ArrayList<Point> pixel = new ArrayList<Point>();
ArrayList<Double> pixelValue = new ArrayList<Double>();
int[][]mat_binaer = new int[400][400];
for(int w = 0;w<400;w++){//x
for(int h = 0;h<400;h++){//y
mat_cost[w][h] = 0;
if(mat_binaer[w][h]==0){
pixel.add(new Point(w,h));
pixelValue.add(startValue);
}
}
}
需要44798 ms = 44,798 s。 我应该使用其他数据结构,如c中的指针吗? 我怎么能在java for android中实现它?
答案 0 :(得分:1)
正如评论中已经提到的那样,pixel
,pixelValue
,new Point(x,y)
和Double.valueOf(double)
更有可能减慢速度。所有这些都会对内存分配器和垃圾收集器造成很大的负担。
new ArrayList<>()
分配一个零容量的arraylist。每次超过该容量时,列表为expanded,从容量12开始,然后每次加倍。以新长度创建新的后备阵列,复制所有项目,并且旧阵列用于垃圾收集。我无法从代码中看出mat_binaer == 0
的频率,但对于160000项,我怀疑你可能正在查看大量的ArrayList扩展。如果您有合理的猜测,您需要添加多少项,请预先分配该大小的ArrayLists,例如new ArrayList<>(1600)
如果您预计有1600件商品。double
添加基元ArrayList<Double>
时,都会使用Double.valueOf()
将其包装在对象中。这些包装中的每一个都在堆上分配一个对象。使用double[]
比使用ArrayList更有效。new Point(x,y)
都会导致对象分配。如果你需要xy坐标,但不是特别需要Point
个对象,那么有两个相同长度的int[]
数组,一个用于x,一个用于y,将有很大的内存效率。这种内存分配通常是慢速代码的嫌疑,但在所有性能调优问题中,您应该尽可能多地尝试在更改内容之前进行测量,例如,使用systrace
。
答案 1 :(得分:0)
这是我目前掌握的知识结果:
我发现普通数组更快,你可以存储经常变化的数据 在一个相对较小的阵列中。让我来表达它。
我像这样初始化数组:
int startValue = Integer.MAX_VALUE;
public static Point[]pixel = new Point[471004];
public static int[]pixelValue= new int[471004];
int count = 0;
for(int w = 0;w<200;w++){//x
for(int h = 0;h<200;h++){//y
mat_cost[w][h] = 0;
if(mat_binaer_0[w][h]==0){
pixel[count]=new Point(w,h);
pixelValue[count]=startValue;
count++;
}
}
}
然后我将Index_first定义为第一个元素的第一个指针 我的大型arraylist和一个Index_last作为我的大型arraylist的最后一个指针。 如果经常更改元素,例如删除第一个元素或添加元素 最后,你必须用另一个类创建这些索引。它被称为 Index_Rotate:
public class Index_Rotate {
private int index;
private int array_position;
public Index_Rotate(int index, int array_position){
this.index= index;
this.array_position = array_position;
}
public void inkrement(){
index++;
if(index>=471004){
index = 0;
array_position++;
}
}
}
如果您从arraylist中删除或添加某些内容,则必须使用inkrement() 使用此方法的arraylist的第一个或最后一个索引。实例 因此,Index_Rotate存在两次。 但要小心,如果第一个元素的array_postion小于1而且 第一个指针的索引小于最后一个指针的索引, 元素将被覆盖。
然而,471004元素的第一次分配非常缓慢。 我在模拟器上尝试了它,只分配了39953个元素,因为 该应用程序一开始只需要这个数量。 上述循环需要3.5秒。
现在: 我在visual studio上用c#做了同样的事情: 在那里,我添加了281334个元素并使用此循环分配它们:
double startValue = Double.MAXVALUE;
LinkedList<Point> pixel = new LinkedList<Point>();
LinkedList<double> pixelValue = new LinkedList<double>();
for (int w = 0; w < width; w++)
{
for (int h = 0; h < height; h++)
{
if (infomatrix[w, h] == 0)
{
pixel.AddLast(new Point(w, h));
pixelValue.AddLast(startValue);
}
}
}
这些是LINKEDLIST,你可以看到,这些是更多的元素 (9倍以上)。此代码仅运行0.0715秒。这是一个非常大的差异。
我的问题:为什么模拟器上的android代码比c#慢得多? 视觉工作室的代码?谢谢你的回答。
答案 2 :(得分:0)
我已经将它实现为java项目而不是android。 没有区别。分配不浪费时间。
这完全是因为模拟器减慢了一切。