簡體   English   中英

Java-將字符串轉換為雙精度的最有效方法

[英]Java - Most efficient way to convert string to double

嗨,我正在從一個文本文件中讀取並將每一行(用逗號分隔)保存到一個數組中。 唯一的問題是,數組中的大多數元素都是雙精度值,其中兩個元素是字符串。 結果,我不得不使該數組成為String []數組。 因此,每當我想對數組中的double值執行某些方程式時,都必須首先將它們解析為double值。 我實際上在運行這些方程式的1000多次迭代,因此我的代碼不斷將字符串解析為雙精度型。 這是一種昂貴的方法,它會減慢我的程序速度。 有沒有一種更好的方法可以將字符串數組中的值轉換為雙精度值,或者在保存文本文件中的行時應該采用更好的方法? 謝謝

這是我從文本文件中讀取后的數組之一:

String[] details = {"24.9", "100.0", "19.2" , "82.0", "Harry", "Smith", "45.0"};

現在,我需要將前2個元素相乘,並將其添加到第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行)執行此操作。 因此,我的程序運行非常緩慢。 有沒有更好的方法可以將字符串值轉換為雙精度? 還是有一種更好的方法應該首先存儲它們?

編輯:我已經使用探查器來檢查代碼的哪一部分是最慢的,的確是我上面顯示的代碼

這是一個生成輸入文件(如您描述的輸入文件)的示例,該輸入文件的長度為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)您的代碼將更加清晰,因為這些字段將被命名,而不是像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();
    }
}

注意還有一個額外的好處,即評分方法現在更強大。 您上面的實現對我們要使用的字段進行了硬編碼,但是通過將這些字段解析並存儲為結構內容,我們可以實現更具可讀性,更可擴展的分數計算方法。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM