您好我正在从文本文件中读取并将每行(用逗号分隔)保存到数组中。唯一的问题是数组中的大多数元素都是double值,其中两个元素是字符串。因此,我必须使数组成为String []数组。因此,每当我想对数组中的double值执行一些方程时,我必须首先将它们解析为double值。我实际上运行了这些方程式的1000多次迭代,因此我的代码不断地将字符串解析为double。这是一种耗费昂贵的方式,这会减慢我的计划。有没有更好的方法可以将字符串数组中的值转换为double值,还是在保存文本文件中的行时应该采取更好的方法?感谢
以下是我从文本文件中读取后的一个数组:
String[] details = {"24.9", "100.0", "19.2" , "82.0", "Harry", "Smith", "45.0"};
我现在需要将前两个元素相乘,并将其添加到第3,第4和第7个元素的总和。换句话说,我只使用数字元素(当然是保存为字符串)
double score = (Double.parseDouble(details[0]) * Double.parseDouble(details[1])) + Double.parseDouble(details[2]) + Double.parseDouble(details[3]) + Double.parseDouble(details[6]);
我必须为文本文件中的每一行(1000多行)执行此操作。因此,我的程序运行速度非常慢。有没有更好的方法可以将字符串值转换为double?还是有一个更好的方法我应该首先存储它们?
编辑:我使用分析器来检查代码的哪一部分是最慢的,而且确实是我上面显示的代码
答案 0 :(得分:4)
这是一个生成输入文件的示例,例如您描述的10000行长的输入文件,然后将其读回并执行您发布的计算并将结果打印到stdout。我在读取文件时专门禁用任何缓冲,以获得最差的读取性能。正如其他人所说,我也没有做任何缓存。整个过程(包括生成文件,进行计算和打印结果)始终需要大约520-550 ms。除非你为数百或数千个文件重复同样的过程,否则这几乎不会“慢”。如果你看到与此截然不同的性能,那么可能是硬件问题。丢失的硬盘可能会使读取性能几乎为零。
import java.io.*;
import java.util.Random;
public class ReadingDoublesFromFileEfficiency {
private static Random random = new Random();
public static void main(String[] args) throws IOException {
long start = System.currentTimeMillis();
String filePath = createInputFile();
BufferedReader reader = new BufferedReader(new FileReader(filePath), 1);
String line;
while ((line = reader.readLine()) != null) {
String[] details = line.split(",");
double score = (Double.parseDouble(details[0]) * Double.parseDouble(details[1])) + Double.parseDouble(details[2]) + Double.parseDouble(details[3]) + Double.parseDouble(details[6]);
System.out.println(score);
}
reader.close();
long elapsed = System.currentTimeMillis() - start;
System.out.println("Took " + elapsed + " ms");
}
private static String createInputFile() throws IOException {
File file = File.createTempFile("testbed", null);
PrintWriter writer = new PrintWriter(new FileWriter(file));
for (int i = 0; i < 10000; i++) {
writer.println(randomLine());
}
writer.close();
return file.getAbsolutePath();
}
private static String randomLine() {
return String.format("%f,%f,%f,%f,%s,%s,%f",
score(), score(), score(), score(), name(), name(), score());
}
private static String name() {
String name = "";
for (int i = 0; i < 10; i++) {
name += (char) (random.nextInt(26) + 97);
}
return name;
}
private static double score() {
return random.nextDouble() * 100;
}
}
答案 1 :(得分:2)
你最好创建一个合适的对象并将值存储在其中 - 这给你带来两大好处:1)你的代码会更快,因为你可以避免不必要的重新计算双值和2)你的代码会更清晰,因为字段将被命名而不是像details[0]
这样调用,而[0]
指的是public class PersonScore {
private double[] multipliers = new double[2];
private double[] summers = new double[3];
private String first;
private String last;
// expects a parsed CSV String
public PersonScore(String[] arr) {
if(arr.length != 7)
throw new InvalidArgumentException("Must pass exactly 7 fields");
multipliers[0] = Double.parseDouble(arr[0]);
multipliers[1] = Double.parseDouble(arr[1]);
summers[0] = Double.parseDouble(arr[2]);
summers[0] = Double.parseDouble(arr[3]);
summers[0] = Double.parseDouble(arr[6]);
first = arr[4];
last = arr[5];
}
public double score() {
double ret = 1;
for(double mult : multipliers)
ret *= mult;
for(double sum : summers)
ret += sum;
return ret;
}
public String toString() {
return first+" "+last+": "+score();
}
}
。
由于2)我不知道这些字段应该是什么,所以显然你的课程看起来会有所不同,但这个想法是一样的:
{{1}}
请注意,还有一个额外的好处,即分数方法现在更加强大。您的实现上面对我们想要使用的字段进行了硬编码,但通过将字段解析并存储为结构内容,我们能够实现更易读,更具伸缩性的分数计算方法。