在Java中声明双精度 - 从ArrayList <double>本地一次或重复一次?

时间:2018-04-18 15:04:21

标签: java eclipse runtime memory-efficient coding-efficiency

我对Java或一般编程中的样式和效率有疑问。以下代码正在阅读一些内容 包含大量常量的文件,用于相当大的计算(此处未显示):

public static void main(String[] args) {

        ArrayList<Double> constants = new ArrayList<Double>();

        try {
            FileReader fr = new FileReader(*PATH*);
            BufferedReader br = new BufferedReader(fr);

            for (String line = br.readLine(); line != null; line = br.readLine()) {
                constants.add(Double.valueOf(line.split("\t")[1]));
            }
        br.close();

        double qh = constants.get(0);      // [1]
        double lambda = constants.get(1);
        ......
        ......
        System.out.println(qh);
     ......
 }

现在:在开始时单独声明每个变量(比如在[1]中)或者在每次在计算中弹出时从ArrayList调用它是否更好(意味着良好的编程风格/运行时效率)?

3 个答案:

答案 0 :(得分:3)

根据需要从ArrayList重复检索它们可能比重用一个名称很好的标识符更不易读。也可能效率稍低,但这可能不重要。

我可能会将这个constants¹的读取从一个文件移到它自己的类中,并将加载的常量暴露为该类的只读成员。这样,main不会被文件读取逻辑混乱,当你使用常量时,它们不仅具有很好的清晰名称,而且它也很清楚(取决于类和实例的命名)他们来自哪里。

¹(如果它们是常量,为什么它们必须在运行时来自文件?)

答案 1 :(得分:2)

在一般程序中将常量存储在Arraylist中之间可能没有什么区别,但如果你暗示你正在使用这些常量进行繁重的计算工作,那么如果你对这些常量进行了大量的改进,你可能会从编译器优化中获益。各种常量作为源代码中的双精度。

就我个人而言,我的观点是arraylist方法过于复杂,并且要求您存储各种常量的索引位置 - 您也可以自己定义常量。

另外,一个例子:

double currentVal = RAYLEY_NUMBER * DIFFUSION_COEFFICIENT;\\

更具描述性
double currentVal = list.get(37) * list.get(44);

这篇文章的后续内容 - 我测试了它。

所以我对Arraylist双打与常数双打感到好奇,我写了一个(不可否认的基本)基准测试用jmh测试它。这些类与我可以做的相同 - 算法是连续乘法和初始值除以每个常数。

class ArraylistTest {
    public static List<Double> constants = new ArrayList<Double>();
    static {
        for(int i = 0; i < 20; i++) {
            constants.add((double)i);
        }
    }
    private int iterations = 1000;
    private double[] results = new double[iterations];

    public void performComplexCalculation() {
        for(int i = 0; i < iterations; i++) {
            double curval = 1.0;

            curval *= constants.get(0);
            curval /= constants.get(1);
            ... 
            curval /= constants.get(19);

            results[i] = curval;
        }
    }
}

class ConstantsTest {
    private int iterations = 1000;
    private double[] results = new double[iterations];

    static Double c1 = 1.0;
    static Double c2 = 2.0;
    ... 
    static Double c20 = 20.0;

    public ConstantsTest() {

    }

    public void performComplexCalculation() {
        for(int i = 0; i < iterations; i++) {
            double curval = 1.0;

            curval *= c1;
            curval /= c2;
            ... 
            curval /= c20;

            results[i] = curval;
        }
    }
}

这些是我从jmh看到的结果:

的ArrayList基

Result: 1841787.017 ±(99.9%) 41096.602 ops/s [Average]
  Statistics: (min, avg, max) = (729913.738, 1841787.017, 2036582.810), stdev = 174005.587
  Confidence interval (99.9%): [1800690.415, 1882883.619]

常量基于

Result: 1841787.017 ±(99.9%) 41096.602 ops/s [Average]
  Statistics: (min, avg, max) = (729913.738, 1841787.017, 2036582.810), stdev = 174005.587
  Confidence interval (99.9%): [1800690.415, 1882883.619]

整体并排

Benchmark                             Mode  Samples        Score  Score error  Units
b.MyBenchmark.testArraylistMethod    thrpt      200  1841787.017    41096.602  ops/s
b.MyBenchmark.testConstantsMethod    thrpt      200  1950015.802    35899.352  ops/s

在我做出的例子中,大约快了6%。在现实案例中,最有可能忽略不计。

答案 2 :(得分:0)

简短的回答是,制作局部变量可能更有效,除非您有许多变量永远不会被使用。

稍微长一点的答案是你不应该担心性能,除非你确定这是一个真正重要的性能瓶颈。在编写代码时担心代码可读性,并且对于性能实际上重要的代码的1%,通过分析找到1%,然后调整它。

但真正的答案是你应该使用属性文件并将值读入你创建的Constants类的实例中。