我对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调用它是否更好(意味着良好的编程风格/运行时效率)?
答案 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看到的结果:
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类的实例中。