2013-03-02 6 views
1

안녕하세요 저는 텍스트 파일에서 읽고 배열 (쉼표로 구분) 각 줄을 저장하고 있습니다. 유일한 문제는 배열의 대부분의 요소가 두 개의 요소가 문자열 인 이중 값입니다. 그 결과 배열을 String [] 배열로 만들어야했습니다. 이 때문에 배열의 double 값에 대한 방정식을 수행 할 때마다 우선 double 값으로 구문 분석해야합니다. 저는 말 그대로이 방정식의 반복 횟수를 1000 회 이상으로 늘 렸습니다. 따라서 코드는 문자열을 계속해서 이중으로 구문 분석합니다. 이것은 비용이 많이 드는 방법으로 내 프로그램 속도를 늦추고 있습니다. 문자열 배열의 값을 double 값으로 변환 할 수있는 더 좋은 방법이 있습니까 아니면 텍스트 파일에서 선을 저장할 때 더 좋은 방법이 있습니까? 여기 자바 - 문자열을 이중으로 변환하는 가장 효율적인 방법

감사

는 배열 중 하나가 내가 텍스트 파일에서 읽은 후 모습입니다 :

String[] details = {"24.9", "100.0", "19.2" , "82.0", "Harry", "Smith", "45.0"}; 
지금은 처음 2 개 요소를 곱하고, 4 제 3의 합에 그것을 추가 할 필요가

및 7 번째 요소. 즉 나는 단지 내가 텍스트 파일 (1000 선)의 모든 한 줄이 작업을 수행해야하는 수치 (당연히 문자열로 저장됩니다) 요소

double score = (Double.parseDouble(details[0]) * Double.parseDouble(details[1])) + Double.parseDouble(details[2]) + Double.parseDouble(details[3]) + Double.parseDouble(details[6]); 

을 사용하고 있습니다. 결과적으로이 프로그램은 매우 느리게 실행됩니다. 문자열 값을 double로 변환 할 수있는 더 좋은 방법이 있습니까? 또는 첫 번째 장소에 보관하는 것이 더 나은 방법이 있습니까?

편집 : 나는 느린입니다 코드의 어느 부분을 확인하기 위해 프로파일 러를 사용했다 그리고 내가

+0

왜 ** ** 한번 변환 **하고 결과를 저장하지 않습니까? –

+8

Double.parseDouble()을 5000 번 호출하면 프로그램이 매우 느리게 실행되지 않습니다. – NPE

+0

@OliCharlesworth - 모든 행이 다릅니다. 서로 다른 값들이 포함됩니다. – Matt9Atkins

답변

4

길이가 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; 
    } 
} 
2

당신은 적절한 개체를 만들고의 값을 저장하기 위해 더 잘 할 줄 위에 표시 한 코드는 참으로 이 코드는 두 가지 주요 이점을 제공합니다. 1) 코드가 더 빠를 것입니다. 두 값을 불필요하게 다시 계산하지 않으므로 코드가 더 명확 해집니다. 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(); 
    } 
} 

공지 사항 추가 혜택, 거기에 그 스코어 메소드가 더욱 강력 해졌습니다. 위의 구현에서 사용하려는 필드를 하드 코딩했지만 구조 콘텐츠로 구문 분석하고 저장하면 더 가독성 있고 확장 성이 뛰어난 점수 계산 방법을 구현할 수 있습니다.

관련 문제