2012-04-19 6 views
2

나는 자바로 작성된 프로그램을 가지고있다.이 프로그램은 단순히 문자열리스트 인 파일을 LinkedHashMap으로 읽어 들인다. 그런 다음 두 개의 열로 구성된 두 번째 파일을 가져오고 각 행에 대해 오른쪽 용어가 HashMap의 용어 중 하나와 일치하는지 확인합니다. 문제는 매우 느리게 실행되고 있다는 것입니다. 여기 자바 -리스트 비교

그것이 HashMap의 조건에 두 번째 파일 비교 곳이며, 코드 조각입니다 :

String output = ""; 

infile = new File("2columns.txt"); 
     try { 
      in = new BufferedReader(new FileReader(infile)); 
     } catch (FileNotFoundException e2) { 
      System.out.println("2columns.txt" + " not found"); 
     } 

     try { 
      fw = new FileWriter("newfile.txt"); 

      out = new PrintWriter(fw); 

      try { 
       String str = in.readLine(); 

       while (str != null) { 
        StringTokenizer strtok = new StringTokenizer(str); 

        strtok.nextToken(); 
        String strDest = strtok.nextToken(); 

        System.out.println("Term = " + strDest); 

        //if (uniqList.contains(strDest)) { 
        if (uniqMap.get(strDest) != null) { 
         output += str + "\r\n"; 
         System.out.println("Matched! Added: " + str); 
        } 

        str = in.readLine(); 
       } 
      } catch (IOException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 

      out.print(output); 

나는의 LinkedHashMap에 처음 ArrayList에로 전환에서 성능 향상을 얻었다을하지만 여전히 시간이 오래 복용 . 이 속도를 높이려면 어떻게해야합니까?

+4

코드를 프로파일 링하고 병목 현상을 찾으십시오. 가장 큰 것을 최적화하십시오. 린스하고 반복하십시오. –

+2

참고 : LinkedHashMap은 요소를 반복 할 때 삽입 순서를 유지하기 위해 모든 값의 '지도'가 아니라 '연결된 목록'을 유지하므로 참고 자료로 LinkCollectionHashMap 대신 HashMap을 사용합니다. 그 특별한 이점이 필요하지 않다면 HashMap으로 바꿀 것입니다. –

+2

@ MДΓΓLLLL에 동의합니다. 응용 프로그램의 속도가 느린 곳에 대한 충분한 정보가 부족합니다. 파일이 너무 커서 앱이 메모리를 디스크에 스왑하고 있습니까? 디스크 IO가 매우 느릴 수 있습니까? 현재 프로그램을 실행하는데 얼마나 걸립니까? 얼마나 빨리 실행해야합니까? WHILE 루프 내에서 새 StringTokenizer를 인스턴스화합니다. 루프 내에서 객체 인스턴스화는 비용이 많이 듭니다. 또한 루프 내에서 System.out.println을 사용하고 있습니다. 파일 크기가 충분하면 인쇄 속도가 느려질 수 있습니다. 느려짐이 어디에서오고 있는지 확인하십시오. –

답변

4

while 루프의 모든 반복에 대해 StringTokenizer를 다시 만드는 것이 병목 현상의 원인 일 수 있습니다. 루프 바깥으로 이동하면 상당히 도움이 될 수 있습니다. 가벼운 업은 String 정의를 while 루프 외부로 이동하여 얻을 수 있습니다.

가장 큰 속도 향상은 아마도 StreamTokenizer을 사용했을 것입니다. 아래 예제를 참조하십시오.

아, 그리고 @Doug 에어즈 위의 댓글에서 말한대로 :

그리고 당신의 코드를 프로파일 링의 MДΓΓ БДLL의 제안 @

가 쾅입니다 대신의 LinkedHashMap의는 HashMap을 사용합니다. 체크 아웃이 Eclipse Profiling Example

Reader r = new BufferedReader(new FileReader(infile)); 
StreamTokenizer strtok = new StreamTokenizer(r); 
String strDest =""; 
while (strtok.nextToken() != StreamTokenizer.TT_EOF) { 
    strDest=strtok.sval; //strtok.toString() might be safer, but slower 
    strtok.nextToken(); 

    System.out.println("Term = " + strtok.sval); 

    //if (uniqList.contains(strDest)) { 
    if (uniqMap.get(strtok.sval) != null) { 
     output += str + "\r\n"; 
     System.out.println("Matched! Added: " + strDest +" "+ strtok.sval); 
    } 

    str = in.readLine(); 
} 

마지막으로 생각은 (그리고 나는이 일에 자신감이 아니에요) 당신이 마지막에 한 번에 그것을 할 경우 파일에 쓰는 것은 또한 빠를 수 있음. 즉 모든 일 치를 일종의 버퍼에 저장하고 한 번의 히트로 기록합니다.

2

StringTokenizer는 레거시 클래스입니다. 권장되는 대체 문자열은 "split"문자열입니다.

일부 시도가 통합되었을 수 있습니다. 한 번의 시도로 여러 개의 캐치를 가질 수 있습니다.

LinkedHashMap 대신 HashMap을 사용하는 것이 좋습니다. 리스트 구조를 유지할 필요가 없기 때문에 smidgeon에서의 get 및 put에 대한 성능이 빠릅니다.

"output"문자열은 String이 아닌 StringBuilder 여야합니다. 그것은 많은 도움이 될 수 있습니다.