Java—将字符串转换为双精度字符串的最有效方法
嗨,我从一个文本文件中读取并将每一行(用逗号分隔)保存到一个数组中。唯一的问题是数组中的大多数元素都是双值,其中as-two元素是字符串。因此,我不得不将数组设置为String[]数组。因此,每当我想对数组中的双精度值执行一些等式时,我必须首先将它们解析为双精度值。实际上,我正在对这些方程进行1000多次迭代,因此我的代码不断地将字符串解析为双精度。这是一个昂贵的方式,这是减慢我的计划。是否有更好的方法将字符串数组中的值转换为双倍值,或者在保存文本文件中的行时有更好的方法?谢谢 下面是我从文本文件读取后其中一个数组的外观:Java—将字符串转换为双精度字符串的最有效方法,java,arrays,string,parsing,double,Java,Arrays,String,Parsing,Double,嗨,我从一个文本文件中读取并将每一行(用逗号分隔)保存到一个数组中。唯一的问题是数组中的大多数元素都是双值,其中as-two元素是字符串。因此,我不得不将数组设置为String[]数组。因此,每当我想对数组中的双精度值执行一些等式时,我必须首先将它们解析为双精度值。实际上,我正在对这些方程进行1000多次迭代,因此我的代码不断地将字符串解析为双精度。这是一个昂贵的方式,这是减慢我的计划。是否有更好的方法将字符串数组中的值转换为双倍值,或者在保存文本文件中的行时有更好的方法?谢谢 下面是我从文本文
String[] details = {"24.9", "100.0", "19.2" , "82.0", "Harry", "Smith", "45.0"};
我现在需要将前两个元素相乘,并将其与第三、第四和第七个元素之和相加。换句话说,我只使用数字元素(当然,这些元素保存为字符串)
我必须对文本文件中的每一行(1000多行)执行此操作。因此,我的程序运行非常缓慢。是否有更好的方法将字符串值转换为双精度?或者,有没有更好的方法来存储它们呢
编辑:我使用探查器检查代码的哪一部分最慢,这确实是我上面显示的代码您最好创建一个适当的对象并将值存储在其中-这给您带来了两个主要好处,1)您的代码将更快,因为您可以避免不必要地重新计算双精度值;2)您的代码将更清晰,因为字段将被命名,而不是像
details[0]
这样的调用,其中完全不清楚[0]
指的是什么
由于2)我不知道字段应该是什么,所以很明显,你的类看起来会不同,但想法是一样的:
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();
}
}
注意,还有一个额外的好处,评分方法现在更加健壮。您上面的实现对我们想要使用的字段进行了硬编码,但通过解析字段并将其存储为结构内容,我们能够实现更可读、更可扩展的分数计算方法。您最好创建一个适当的对象并将值存储在其中-这给您带来了两个主要好处,1)您的代码将更快,因为您可以避免不必要地重新计算双精度值;2)您的代码将更清晰,因为字段将被命名,而不是像
details[0]
这样的调用,其中完全不清楚[0]
指的是什么
由于2)我不知道字段应该是什么,所以很明显,你的类看起来会不同,但想法是一样的:
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();
}
}
注意,还有一个额外的好处,评分方法现在更加健壮。您上面的实现对我们想要使用的字段进行了硬编码,但是通过解析字段并将其存储为结构内容,我们能够实现一种更可读、更可扩展的分数计算方法。下面是一个生成输入文件的示例,如您所描述的10000行长的输入文件,然后将其读入并进行发布的计算,并将结果打印到stdout。我特别在读取文件时禁用任何缓冲,以获得最差的读取性能。正如其他人所建议的,我也没有做任何缓存。整个过程,包括生成文件、进行计算和打印结果,始终需要大约520-550毫秒。这并不“慢”,除非你对数百或数千个文件重复同样的过程。如果您看到与此截然不同的性能,那么可能是硬件问题。出现故障的硬盘会使读取性能几乎为零
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;
}
}
import java.io.*;
导入java.util.Random;
公共类读取使文件效率提高一倍{
私有静态随机=新随机();
公共静态void main(字符串[]args)引发IOException{
长启动=System.currentTimeMillis();
字符串filePath=createInputFile();
BufferedReader reader=新BufferedReader(新文件读取器(文件路径),1);
弦线;
而((line=reader.readLine())!=null){
String[]details=line.split(“,”);
double score=(double.parseDouble(细节[0])*double.parseDouble(细节[1])+double.parseDouble(细节[2])+double.parseDouble(细节[3])+double.parseDouble(细节[6]);
系统输出打印项次(分数);
}
reader.close();
长时间运行=System.currentTimeMillis()-开始;
System.out.println(“take”+经过时间+“ms”);
}
私有静态字符串createInputFile()引发IOException{
File File=File.createTempFile(“测试床”,null);
PrintWriter writer=新的PrintWriter(新的FileWriter(文件));
对于(int i=0;i<10000;i++){
writer.println(randomLine());
}
writer.close();
返回文件.getAbsolutePath();
}
私有静态字符串randomLine(){
返回字符串.format(“%f,%f,%f,%f,%s,%s,%f”,
score(),score(),score(),score(),name(),name(),score());
}
私有静态字符串名称(){
字符串名称=”;
对于(int i=0;i<10;i++){
name+=(char)(random.nextInt(26)+97);
}
返回名称;
}
私有静态双倍分数(){
返回random.nextDouble()*100;
}
}
下面是一个生成输入文件的示例,如您所描述的10000行长的输入文件,然后将其读回并进行发布的计算,并将结果打印到stdout。我特别在读取文件时禁用任何缓冲,以获得最差的读取性能。正如其他人所建议的,我也没有做任何缓存。Th