Roh*_*dey 4 java memory median
我正在使用java程序从数据库中获取一些数据.然后我计算一些数字并开始将它们存储在一个数组中.我正在使用的机器有4台RAM.现在,我不知道预先会有多少数字,所以我使用了ArrayList<Double>.但是我知道会有大致的数字300 million numbers.
因此,由于一个double是8个字节,因此该数组将消耗的内存的粗略估计是2.4 gigs(可能更多是因为ArrayList的开销).在此之后,我想计算这个数组的中位数,并使用org.apache.commons.math3.stat.descriptive.rank.Median作为double[]数组输入的库.所以,我需要转换ArrayList<Double>为double[].
我确实看到了很多问题,并且他们都提到没有办法绕过整个阵列.现在这很好,但由于它们也将两个对象都保存在内存中,这使我的内存需求高达4.8演出.现在我们遇到了一个问题,因为总RAM可用我们4演出.
首先,我怀疑该程序在某些时候会给我一个正确的内存错误(它当前正在运行)?如果是这样,我如何计算中位数而不必分配双倍内存?我想避免排序数组,因为计算中位数是O(n).
您的问题甚至比您意识到的还要糟糕,因为ArrayList<Double>每个条目的效率要低于8个字节.每个条目实际上都是一个对象,ArrayList保留一组引用.一个Double对象可能大约12个字节(某种类型标识符为4个字节,double自身为8个字节),对它的引用又增加了4个,每个条目总共最多16个字节,甚至不包括内存管理的开销和这样.
如果约束条件稍微宽一些,您可以实现自己DoubleArray的支持,double[]但知道如何调整自身大小.但是,调整大小意味着您必须同时在内存中保留旧数组和新数组的副本,同时还要限制内存限制.
这仍然留下一些选择:
循环输入两次; 一旦计算条目,一次将它们读成合适的大小double[].当然,这取决于您输入的性质是否可行.
对最大输入大小(可能是用户可配置的)做出一些假设,并分配一个double[]这个固定大小的前端.仅使用填充的部分.
使用float而不是double将内存需求减少一半,但会牺牲一些精度.
重新思考您的算法,以避免一次将所有内容保存在内存中.