2013-07-05 24 views
5
{ 
    StringBuilder fileBuff = new StringBuilder(); 
    long before = getUsedMem(); 
    try { 
    //Open InputStreamReader here 
     while ((currLine = lnr.readLine()) != null) { 
      fileBuff.append("\r\n" + currLine); 
     } 
    //Close streams 
    } catch (Exception e) { 
     e.printStackTrace(); 
    } 
    System.out.println("usedTotal: " + (getUsedMem() - before)); 
} 

private long getUsedMem() { 
    return Runtime.getRuntime().totalMemory() - Runtime.getRuntime().freeMemory(); 
} 

Trong khi chạy mã nhiều lần, tôi nhận được usedTotal ~ 14.279.888, nhưng nếu tôi thay thế với fileBuff.append("\r\n").append(currLine) tôi nhận được gần gấp đôi bộ nhớ ~ 33.264.440.
Ai đó có thể giải thích lý do, như tôi biết String nối cũng sử dụng StringBuilder?StringBuilder sử dụng bộ nhớ hơn khi append được sử dụng

I: fileBuff.append ("\ r \ n" + currLine);

 62: aload   6 
    64: invokevirtual #16     // Method java/io/LineNumberReader.readLine:()Ljava/lang/String; 
    67: dup   
    68: astore_2  
    69: ifnull  99 
    72: aload_1  
    73: new   #2     // class java/lang/StringBuilder 
    76: dup   
    77: invokespecial #3     // Method java/lang/StringBuilder."<init>":()V 
    80: ldc   #17     // String \r\n 
    82: invokevirtual #8     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    85: aload_2  
    86: invokevirtual #8     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    89: invokevirtual #10     // Method java/lang/StringBuilder.toString:()Ljava/lang/String; 
    92: invokevirtual #8     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    95: pop   
    96: goto   62 

II fileBuff.append ("\ r \ n"). Append (currLine)

 62: aload   6 
    64: invokevirtual #16     // Method java/io/LineNumberReader.readLine:()Ljava/lang/String; 
    67: dup   
    68: astore_2  
    69: ifnull  86 
    72: aload_1  
    73: ldc   #17     // String \r\n 
    75: invokevirtual #8     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    78: aload_2  
    79: invokevirtual #8     // Method java/lang/StringBuilder.append:(Ljava/lang/String;)Ljava/lang/StringBuilder; 
    82: pop   
    83: goto   62 

Rõ ràng #II nên sử dụng ít bộ nhớ, nhưng nó không. Tập tin tôi đọc dài 50k.

+2

"* StringBuilder sử dụng nhiều bộ nhớ hơn khi nối thêm được sử dụng *". Có nó, vì vậy mảng sẽ không được mở rộng mỗi khi một cái gì đó được nối thêm. – johnchen902

+0

@ johnchen902 Tôi nghĩ rằng đây phải là câu trả lời, không phải là bình luận ... – Puce

+0

@Puce Không phải là câu trả lời khi tôi không tìm thấy bằng chứng. – johnchen902

Trả lời

5

Khi sử dụng StringBuilder, bạn đang đặt chỗ để thêm chuỗi vào bộ đệm của mình. Đây là một ví dụ tốt để sử dụng StringBuilder thay vì chuỗi vì bạn đang sử dụng vòng lặp while.

Khi bạn đang sử dụng một String, mỗi khi bạn gõ một cái gì đó như thế này:

String s = s + someOtherString; 

Bạn đang ném đi s chuỗi hiện tại của bạn và tạo ra một cái mới để đi thay vì nó là s + someOtherString. Điều này có nghĩa rằng bạn liên tục cần bộ nhớ mới để tạo chuỗi ghép nối, ném chuỗi cũ ra và đặt tham chiếu biến của bạn vào chuỗi mới của bạn.

Với StringBuilder bạn có thể nối thêm vào chuỗi của mình mà không phải xóa phần hiện tại.

Vì vậy, có, nó sử dụng nhiều bộ nhớ hơn, nhưng nó rất hiệu quả trong một số trường hợp so với chỉ sử dụng một chuỗi.

Nói cách khác: Stringimmutable objectStringBuilder thì không.


Trong mã của bạn:

fileBuff.append("\r\n" + currLine); 

Đây là giống như new String("\r\n" + currLine); đó là 1 đối tượng String

Bạn đang sử dụng 1 append.

Trong bình luận của bạn, bạn nói rằng nếu bạn sử dụng này:

fileBuff.append("\r\n").append(currLine); 

Đây là giống như new String("\r\n");new String(currLine); đó là 2 chuỗi các đối tượng

Bạn nhận được gần như gấp đôi so với bộ nhớ. Điều đó có ý nghĩa bởi vì bạn đang làm 2x nối ​​thêm, do đó sử dụng gấp đôi bộ nhớ.

+0

Xin chào, tôi đã sử dụng StringBuilder, hiệu quả hơn StringBuffer. Ngoài ra, tôi nhận được sử dụng bộ nhớ cao hơn trong khi không sử dụng chuỗi nối. Nếu tôi sử dụng s = s + someOtherString, tôi chỉ sử dụng một nửa bộ nhớ. – CristiL

+0

Ồ, tôi đặt 'Stringbuffer' thay vì' StringBuilder' Tôi xin lỗi! Tôi đã thay đổi nó ngay bây giờ – JREN

+0

Tôi đồng ý với bạn rằng lý thuyết nói rằng, nhưng trong thực tế có vẻ như nó không giống nhau: fileBuff.append ("\ r \ n" + currLine) sẽ sử dụng ít bộ nhớ hơn fileBuff.append ("\ r \ n "). append (currLine) – CristiL

1

Tôi muốn viết thư này làm nhận xét về câu trả lời @JRENs nhưng tôi không có đủ đại diện.Lý do 2 gắn thêm mất nhiều bộ nhớ là ở đây http://docs.oracle.com/javase/tutorial/java/data/buffers.html

Các hoạt động chủ yếu trên một StringBuilder mà không có sẵn trong chuỗi là append() và chèn() phương pháp, mà đang bị quá tải để chấp nhận dữ liệu của bất kỳ loại . Mỗi chuyển đổi đối số của nó thành một chuỗi và sau đó nối thêm hoặc chèn các ký tự của chuỗi đó vào chuỗi ký tự trong trình tạo chuỗi.

Vì vậy, mỗi hoạt động nối thêm tạo một Chuỗi mới, đó là lý do tại sao 2 phụ thêm (mỗi vòng lặp) mất khoảng gấp đôi bộ nhớ khi thêm một bộ nhớ.

+0

Chuyển đổi và thể hiện chuỗi mới chỉ trong trường hợp các phương thức quá tải. Nếu bạn nhìn vào append (String), nó không tạo ra một thể hiện String mới. – CristiL

Các vấn đề liên quan