การล้างสตริงบัฟเฟอร์ / ตัวสร้างหลังจากลูป


122

คุณจะล้างบัฟเฟอร์สตริงใน Java หลังจากการวนซ้ำได้อย่างไรดังนั้นการวนซ้ำครั้งถัดไปจึงใช้บัฟเฟอร์สตริงที่ชัดเจน


2
คำถามอื่น: ทำไมคุณถึงใช้ SB เพื่อการวนซ้ำเพียงครั้งเดียว? มีการทำซ้ำภายในอีกหรือไม่? SB ไม่คุ้มค่าหากคุณเพียงแค่ต้องการทำ A + B + C + D (คอมไพเลอร์ Java จะใช้ SB ภายใน) ช่วยได้หากคุณต้องการเพิ่มส่วนต่างๆของสตริงตามเงื่อนไข แต่อย่างอื่น ... เพียงแค่ใช้ "+"
helios

คำตอบ:


135

ทางเลือกหนึ่งคือใช้วิธีการลบดังนี้:

StringBuffer sb = new StringBuffer();
for (int n = 0; n < 10; n++) {
   sb.append("a");

   // This will clear the buffer
   sb.delete(0, sb.length());
}

อีกทางเลือกหนึ่ง (ตัวล้างบิต) ใช้setLength (int len) :

sb.setLength(0);

ดูJavadocสำหรับข้อมูลเพิ่มเติม:


15
สิ่งที่ขยะน้อยกว่าเล็กน้อยคือการประกาศ StringBuffer ภายในลูป
Mark Elliot

11
อ่าฉันคิดว่า sb.setLength (0); สะอาดและมีประสิทธิภาพมากกว่าการประกาศภายในลูป โซลูชันของคุณขัดกับประโยชน์ด้านประสิทธิภาพของการใช้ StringBuffer ...
จอน

6
ฉันคิดว่าประโยชน์ด้านประสิทธิภาพมาจากความไม่แน่นอนของสตริงไม่ใช่จากการบันทึกอินสแตนซ์ นี่คือการทดสอบอย่างรวดเร็วของการทำซ้ำ 1e8: วงใน (2.97s): ideone.com/uyyTL14w , วงนอก (2.87s): ideone.com/F9lgsIxh
Mark Elliot

6
การพูดถึงประสิทธิภาพ: เว้นแต่ว่ารหัสของคุณจะถูกเข้าถึงในสถานการณ์แบบมัลติเธรดคุณควรใช้ StringBuilder มากกว่า StringBuffer - ดู javadoc: "หากเป็นไปได้ขอแนะนำให้ใช้คลาสนี้ตามความต้องการของ StringBuffer เนื่องจากจะเร็วกว่าภายใต้ การนำไปใช้งานมากที่สุด ".
Rahel Lüthy

4
ประโยชน์เพียงอย่างเดียวของการสร้าง SB ภายนอกคือไม่สูญเสียถ่านภายใน (อาจยาว) ของมัน ถ้าในตัววนซ้ำตัวแรกมันโตพอลูปที่สองก็ไม่จำเป็นต้องปรับขนาดถ่าน [] ใด ๆ แต่เพื่อให้ได้เปรียบ "วิธีการที่ชัดเจน" จะต้องรักษาขนาดของอาร์เรย์ภายใน setLength ทำเช่นนั้น แต่ยังตั้งค่าเป็น \ u0000 อักขระที่ไม่ได้ใช้ทั้งหมดใน SB ดังนั้นจึงมีประสิทธิภาพน้อยกว่าเพียงแค่สร้าง SB ใหม่ที่มีความจุเริ่มต้นที่ดี ประกาศภายในวงจะดีกว่า
helios

48

วิธีที่ง่ายที่สุดในการนำกลับมาใช้ใหม่StringBufferคือการใช้วิธีนี้setLength()

public void setLength(int newLength)

คุณอาจมีกรณีเช่น

StringBuffer sb = new StringBuffer("HelloWorld");
// after many iterations and manipulations
sb.setLength(0);
// reuse sb

2
@MMahmoud ในตัวอย่างรหัสที่มันควรอ่านแทนsetLength setlength
OnaBai

เมื่อฉันเห็นซอร์สโค้ด setLength มันทำงานอย่างไร ( gist.github.com/ebuildy/e91ac6af2ff8a6b1821d18abf2f8c9e1 ) ที่นี่จำนวนจะมากกว่า newLength (0) เสมอ
Thomas Decaux

20

คุณมีสองทางเลือก:

ใช้อย่างใดอย่างหนึ่ง:

sb.setLength(0);  // It will just discard the previous data, which will be garbage collected later.  

หรือใช้:

sb.delete(0, sb.length());  // A bit slower as it is used to delete sub sequence.  

บันทึก

หลีกเลี่ยงการประกาศStringBufferหรือStringBuilderวัตถุภายในลูปมิฉะนั้นจะสร้างออบเจ็กต์ใหม่เมื่อทำซ้ำแต่ละครั้ง การสร้างวัตถุต้องใช้ทรัพยากรระบบพื้นที่และต้องใช้เวลาด้วย ดังนั้นในระยะยาวหลีกเลี่ยงการประกาศภายในลูปถ้าเป็นไปได้



5

ฉันขอแนะนำให้สร้างใหม่StringBuffer(หรือดีกว่าStringBuilder) สำหรับการทำซ้ำแต่ละครั้ง ความแตกต่างของประสิทธิภาพนั้นเล็กน้อยมาก แต่โค้ดของคุณจะสั้นลงและเรียบง่ายกว่า


2
หากคุณมีหลักฐานเกี่ยวกับความแตกต่างของประสิทธิภาพดังกล่าวโปรดแบ่งปัน (ฉันยินดีที่จะเห็นสถิติว่าส่วนใหญ่ใช้ Java ที่ไหนและคำจำกัดความของ "ส่วนใหญ่" อยู่ภายใต้คำจำกัดความใด)
Eli Acherkan

1
เป็นที่ทราบกันดีว่าการจัดสรร (คีย์เวิร์ดใหม่ใน Java) มีราคาแพงกว่าการเปลี่ยนฟิลด์บางฟิลด์ของอ็อบเจ็กต์เดียวกัน สำหรับ "ส่วนใหญ่" ซึ่งคุณสามารถแทนที่ได้อย่างมากมีอุปกรณ์ Android มากกว่า 1.5 พันล้านเครื่องทั้งหมดใช้ Java
Louis CAD

1
ฉันยอมรับว่าในบางกรณีความสามารถในการอ่านโค้ดมีความสำคัญมากกว่าประสิทธิภาพ แต่ในกรณีนี้รหัสเป็นเพียงบรรทัดเดียว! และคุณสามารถเรียกใช้เกณฑ์มาตรฐานซึ่งจะพิสูจน์ให้คุณเห็นว่าการจัดสรรและการสร้างวัตถุรวมทั้งการเก็บขยะมีราคาแพงกว่าการไม่ทำเลย ในขณะที่เราอยู่ในวงมันมีความเกี่ยวข้องมากกว่า
Louis CAD

1
ฉันยังสมัครรับข้อมูลมุมมองของ Knuth แต่มุมมองของเขาไม่ได้เป็นความจริงเสมอไป การเพิ่มเพียงบรรทัดเดียวเพื่อให้ได้วงจร CPU และหน่วยความจำก็ไม่ได้ชั่วร้ายอย่างแน่นอน คุณมีความคิดที่ตรงเกินไป โปรดทราบว่าโดยปกติการวนซ้ำหลาย ๆ ครั้ง การวนซ้ำสามารถทำซ้ำได้หลายพันครั้งซึ่งสามารถกินเมกะไบต์อันมีค่าบนมือถือ (และบนเซิร์ฟเวอร์หรือคอมพิวเตอร์) หากไม่ได้รับการปรับให้เหมาะสมอย่างรอบคอบ
Louis CAD

1
ฉันคิดว่าเราทั้งคู่ระบุมุมมองของเราไว้อย่างชัดเจนเพียงพอและฉันรู้สึกว่าการสนทนาเพิ่มเติมจะไม่เป็นประโยชน์ต่อส่วนความคิดเห็นนี้ หากคุณรู้สึกว่าคำตอบของฉันไม่ถูกต้องทำให้เข้าใจผิดหรือไม่สมบูรณ์คุณหรือใครก็ตามก็สามารถแก้ไขและ / หรือลงคะแนนได้
Eli Acherkan

5
public void clear(StringBuilder s) {
    s.setLength(0);
}

การใช้งาน:

StringBuilder v = new StringBuilder();
clear(v);

เพื่อให้อ่านง่ายฉันคิดว่านี่เป็นทางออกที่ดีที่สุด


2

มีคำตอบที่ดีอยู่แล้ว เพียงเพิ่มผลการเปรียบเทียบสำหรับความแตกต่างของประสิทธิภาพ StringBuffer และ StringBuild ใช้อินสแตนซ์ใหม่ในลูปหรือใช้ setLength (0) ในลูป

สรุปคือ: ในวงใหญ่

  • StringBuilder เร็วกว่า StringBuffer มาก
  • สร้างอินสแตนซ์ StringBuilder ใหม่ในลูปไม่มีความแตกต่างกับ setLength (0) (setLength (0) มีข้อได้เปรียบเล็กน้อยมากกว่าการสร้างอินสแตนซ์ใหม่)
  • StringBuffer ช้ากว่า StringBuilder โดยสร้างอินสแตนซ์ใหม่ในลูป
  • setLength (0) ของ StringBuffer ช้ากว่าการสร้างอินสแตนซ์ใหม่ในลูปมาก

เกณฑ์มาตรฐานที่ง่ายมาก (ฉันเพิ่งเปลี่ยนรหัสด้วยตนเองและทำการทดสอบอื่น):

public class StringBuilderSpeed {
public static final char ch[] = new char[]{'a','b','c','d','e','f','g','h','i'};

public static void main(String a[]){
    int loopTime = 99999999;
    long startTime = System.currentTimeMillis();
    StringBuilder sb = new StringBuilder();
    for(int i = 0 ; i < loopTime; i++){
        for(char c : ch){
            sb.append(c);
        }
        sb.setLength(0);
    }
    long endTime = System.currentTimeMillis();
    System.out.println("Time cost: " + (endTime - startTime));
}

}

อินสแตนซ์ StringBuilder ใหม่ในลูป: ต้นทุนเวลา: 3693, 3862, 3624, 3742

StringBuilder setLength: ต้นทุนเวลา: 3465, 3421, 3557, 3408

อินสแตนซ์ StringBuffer ใหม่ในลูป: ต้นทุนเวลา: 8327, 8324, 8284

StringBuffer setLength Time cost: 22878, 23017, 22894

อีกครั้ง StringBuilder setLength เพื่อให้แน่ใจว่าห้องปฏิบัติการของฉันไม่ได้มีปัญหาในการใช้ความยาวเช่นนี้สำหรับ StringBuffer setLength :-) ค่าเวลา: 3448


0
StringBuffer sb = new SringBuffer();
// do something wiht it
sb = new StringBuffer();

ฉันคิดว่ารหัสนี้เร็วกว่า


3
ซึ่งจะมีปัญหาด้านประสิทธิภาพ มันจะสร้างวัตถุใหม่หลังจากการทำซ้ำทุกครั้ง
Aditya Singh

@AdityaSingh มันเป็นแนวทางที่สมเหตุสมผล อย่าถือว่าปัญหาด้านประสิทธิภาพโดยไม่มีหลักฐาน
shmosel

การตั้งสมมติฐานตามความเข้าใจในสิ่งที่เกิดขึ้นเป็นพื้นฐานของสติปัญญา
rghome
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.