在android快速查找/存储2d为int,double [400] [400]数组

时间:2015-06-21 11:15:30

标签: java android arrays

我想在[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中实现它?

3 个答案:

答案 0 :(得分:1)

正如评论中已经提到的那样,pixelpixelValuenew 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。 没有区别。分配不浪费时间。

这完全是因为模拟器减慢了一切。