优化性能:Java 中用于数值计算的基元类型的 ArrayList 的替代方案<Double>

问题描述 投票:0回答:1

我知道Stack Overflow上可能有一些看似类似的问题;然而,我的问题不同。

我目前正在从事特定研究领域的数值计算,并继承了我的团队很早以前实现的一个Java包。我现在的任务是优化它的性能。该软件包广泛使用了

ArrayList<Double>

。据我所知,由于Java泛型中的类型擦除,Java,至少到我正在使用的版本9,不支持原始类型
ArrayList

这有几个问题:

  1. 存储开销:Double 是 double 的包装类。由于Double是一个对象,它包含一个对象头,占用8个字节。因此,每个Double对象占用16字节的内存。

  2. 非连续内存ArrayList

    内部使用数组来存储
    Double
    对象,即
    Double[] data
    。该数组保存对 
    Double
     实例的引用。这些实例不连续存储在堆中。例如,如果 
    Double[] data = {1.0, 2.0}
    ,则数据中的引用是连续的,但这些引用指向的实际 
    Double
     对象不是连续的。由于需要取消引用这些指针,这会导致局部性差和频繁的缓存未命中。

  3. 拆箱和自动装箱:使用 Double 进行比较和计算时,由于拆箱和自动装箱,会产生额外的开销。

我的问题是:

  1. 最新版本的 Java 中是否有任何新功能允许将 ArrayList 与原始类型一起使用?

  2. 是否有任何实验性功能或框架支持此功能?

  3. 如果没有,通过将

    DoubleArrayList

     源代码中的所有 Object 替换为原始 double 来创建个人 
    ArrayList
     是否可行?这种方法有哪些潜在的陷阱?

PS:

  1. 我们的日程非常紧张,没有时间用 C++ 重写整个包,其中

    vector<double>

     可用。

  2. 在我们的用例中,容器在计算过程中会改变大小,而我们事先不知道大小。因此,我们必须使用可调整大小的数组(例如

    ArrayList

    )而不是
    double[]

java arraylist
1个回答
0
投票
使用

double[]

ArrayList

的“自由”调整大小只是一种便利 - 当需要更多空间时,内部支持数组会被替换为两倍大,并使用旧式循环复制元素。

您自己编写代码是一个简单的实现。

创建一个带有

double[]

 字段的类,基本上从 
ArrayList
 复制您需要的内容,但为数组添加 getter 方法并将其用于计算。

如果你能摆脱它,请使用

float[]

 代替,因为 
float
 上的操作大约是 
double
 上的两倍。

© www.soinside.com 2019 - 2024. All rights reserved.