JavaRush /จาวาบล็อก /Random-TH /รู้เบื้องต้นเกี่ยวกับ String, StringBuffer และ StringBuil...

รู้เบื้องต้นเกี่ยวกับ String, StringBuffer และ StringBuilder ใน Java

เผยแพร่ในกลุ่ม
Java มีคลาสอยู่สามคลาสสำหรับการทำงานกับข้อมูลข้อความ: String , StringBufferและStringBuilder นักพัฒนาทุกคนต้องเผชิญกับคนแรกตั้งแต่เริ่มต้นการเรียนรู้ภาษา แล้วอีกสองคนที่เหลือล่ะ? อะไรคือความแตกต่างและเมื่อใดจะดีกว่าถ้าใช้คลาสใดคลาสหนึ่ง? โดยทั่วไปความแตกต่างระหว่างพวกเขามีน้อย แต่เป็นการดีกว่าที่จะเข้าใจทุกอย่างในทางปฏิบัติ :) รู้เบื้องต้นเกี่ยวกับ String, StringBuffer และ StringBuilder ใน Java - 1

คลาสสตริง

คลาสนี้แสดงถึงลำดับของอักขระ ตัวอักษรสตริงทั้งหมดที่กำหนดไว้ในโปรแกรม เช่น "นี่คือสตริง" เป็นอินสแตนซ์ของคลาสสตริง String มีคุณสมบัติพื้นฐานสองประการ:
  • นี่คือคลาสที่ไม่เปลี่ยนรูป
  • นี่คือชั้นเรียนสุดท้าย
โดยทั่วไป คลาส String ไม่สามารถมีลูก ( final) และอินสแตนซ์ของคลาสไม่สามารถแก้ไขได้หลังจากการสร้าง ( immutable) สิ่งนี้ทำให้คลาส String มีข้อดีที่สำคัญหลายประการ:
  1. เนื่องจากความไม่เปลี่ยนรูป แฮชโค้ดของอินสแตนซ์ของคลาส String จึงถูกแคชไว้ ไม่จำเป็นต้องประเมินทุกครั้งเนื่องจากค่าฟิลด์ของออบเจ็กต์จะไม่เปลี่ยนแปลงหลังจากสร้างขึ้น สิ่งนี้ให้ประสิทธิภาพสูงเมื่อใช้คลาสนี้เป็นคีย์สำหรับHashMap.

  2. คลาส String สามารถใช้ในสภาพแวดล้อมแบบมัลติเธรดโดยไม่ต้องซิงโครไนซ์เพิ่มเติม

  3. คุณสมบัติอื่นของคลาส String ก็คือมันโอเวอร์โหลด+ตัวดำเนินการ " " ใน Java ดังนั้นการต่อ (การบวก) ของสตริงเข้าด้วยกันจึงค่อนข้างง่าย:

public static void main(String[] args) {
    String command = "Follow" + " " + "the" + " " + "white" + " " + "rabbit";
    System.out.println(command); // Follow the white rabbit
}
ภายใต้ประทุน การต่อสตริงจะดำเนินการโดยคลาส StringBuilder หรือ StringBuffer (ขึ้นอยู่กับดุลยพินิจของคอมไพเลอร์) และวิธีการappend(เราจะพูดถึงคลาสเหล่านี้ในภายหลัง) หากเราเพิ่มอินสแตนซ์ของคลาส String เข้ากับอินสแตนซ์ของคลาสอื่น คลาสหลังจะถูกลดทอนเป็นการแสดงสตริง:
public static void main(String[] args) {
    Boolean b = Boolean.TRUE;
    String result = "b is " + b;
    System.out.println(result); //b is true
}
นี่เป็นคุณสมบัติที่น่าสนใจอีกประการหนึ่งของคลาส String: อ็อบเจ็กต์ของคลาสใด ๆ สามารถแปลงเป็นการแสดงสตริงได้โดยใช้วิธีการtoString()ที่กำหนดในคลาสObjectและสืบทอดโดยคลาสอื่นทั้งหมด บ่อยครั้งที่วิธีการ toString() บนวัตถุถูกเรียกโดยปริยาย ตัวอย่างเช่น เมื่อเราแสดงบางสิ่งบนหน้าจอหรือเพิ่ม String ให้กับอ็อบเจ็กต์ของคลาสอื่น คลาส String มีอีกหนึ่งคุณสมบัติ ตัวอักษรสตริงทั้งหมดที่กำหนดในโค้ด Java เช่น "asdf" จะถูกแคช ณ เวลาคอมไพล์ และเพิ่มลงในกลุ่มสตริงที่เรียกว่า หากเรารันโค้ดต่อไปนี้:
String a = "Wake up, Neo";
String b = "Wake up, Neo";

System.out.println(a == b);
เราจะเห็น เป็นจริง ในคอนโซลเนื่องจากตัวแปรaจะbอ้างถึงอินสแตนซ์เดียวกันของคลาส String ที่ถูกเพิ่มลงในพูลสตริงในขณะคอมไพล์ นั่นคือจะไม่สร้างอินสแตนซ์ที่แตกต่างกันของคลาสที่มีค่าเดียวกัน และหน่วยความจำจะถูกบันทึกไว้

ข้อบกพร่อง:

เดาได้ไม่ยากว่าคลาส String จำเป็นสำหรับการทำงานกับสตริงเป็นหลัก แต่ในบางกรณี คุณสมบัติข้างต้นของคลาส String สามารถเปลี่ยนจากข้อดีเป็นข้อเสียได้ เมื่อสร้างสตริงในโค้ด Java แล้ว การดำเนินการหลายอย่างมักจะดำเนินการกับสตริงเหล่านั้น:
  • การแปลงสตริงเป็นรีจิสเตอร์ที่แตกต่างกัน
  • การสกัดสตริงย่อย
  • การต่อข้อมูล;
  • ฯลฯ
ลองดูรหัสนี้:
public static void main(String[] args) {

    String s = " Wake up, Neo! ";
    s = s.toUpperCase();
    s = s.trim();

    System.out.println("\"" + s + "\"");
}
ดูเผินๆ เหมือนเราเพิ่งแปลคำว่า Wake up, Neo! เป็นตัวพิมพ์ใหญ่ ลบช่องว่างเพิ่มเติมออกจากสตริงนี้แล้วใส่เครื่องหมายคำพูด ในความเป็นจริง เนื่องจากความไม่เปลี่ยนแปลงของคลาส String ซึ่งเป็นผลมาจากการดำเนินการแต่ละครั้ง อินสแตนซ์สตริงใหม่และอินสแตนซ์สตริงเก่าจะถูกละทิ้ง ทำให้เกิดขยะจำนวนมาก จะหลีกเลี่ยงการสูญเสียหน่วยความจำได้อย่างไร?

คลาส StringBuffer

ในการจัดการกับการสร้างขยะชั่วคราวเนื่องจากการปรับเปลี่ยนวัตถุ String คุณสามารถใช้คลาส StringBuffer นี่คือmutableชั้นเรียนเช่น เปลี่ยนแปลงได้ อ็อบเจ็กต์ของคลาส StringBuffer สามารถมีชุดอักขระเฉพาะ ความยาวและค่าที่สามารถเปลี่ยนแปลงได้โดยการเรียกเมธอดบางอย่าง มาดูกันว่าคลาสนี้ทำงานอย่างไร หากต้องการสร้างวัตถุใหม่ ให้ใช้ตัวสร้างตัวใดตัวหนึ่ง เช่น:
  • StringBuffer() - จะสร้างวัตถุว่าง (ไม่มีอักขระ)
  • StringBuffer(String str) - จะสร้างวัตถุตามตัวแปร str (ประกอบด้วยอักขระทั้งหมดของ str ในลำดับเดียวกัน)
ฝึกฝน:
StringBuffer sb = new StringBuffer();
StringBuffer sb2 = new StringBuffer("Not empty");
การต่อสตริงผ่าน StringBuffer ใน Java ทำได้โดยใช้นามสกุลappend. โดยทั่วไป วิธีการappendในคลาส StringBuffer จะถูกโอเวอร์โหลดในลักษณะที่สามารถรับข้อมูลได้เกือบทุกประเภท:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2));
    sb.append("; ");
    sb.append(false);
    sb.append("; ");
    sb.append(Arrays.asList(1,2,3));
    sb.append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
วิธีการappendส่งคืนอ็อบเจ็กต์ที่ถูกเรียก (เช่นเดียวกับวิธีอื่น ๆ ) ซึ่งช่วยให้สามารถเรียกเป็น "ลูกโซ่" ได้ ตัวอย่างข้างต้นสามารถเขียนได้ดังนี้:
public static void main(String[] args) {
    StringBuffer sb = new StringBuffer();

    sb.append(new Integer(2))
            .append("; ")
            .append(false)
            .append("; ")
            .append(Arrays.asList(1,2,3))
            .append("; ");

    System.out.println(sb); // 2; false; [1, 2, 3];
}
คลาส StringBuffer มีหลายวิธีในการทำงานกับสตริง เรามาแสดงรายการหลักๆ:
  • delete(int start, int end)— ลบสตริงย่อยของอักขระเริ่มต้นจากตำแหน่งstartสิ้นสุดend
  • deleteCharAt(int index)— ลบตัวละครในตำแหน่งindex
  • insert(int offset, String str)— แทรกบรรทัดstrที่ตำแหน่งoffset. วิธีการนี้insertยังมีการโอเวอร์โหลดและสามารถรับข้อโต้แย้งที่แตกต่างกันได้
  • replace(int start, int end, String str)- จะแทนที่อักขระทั้งหมดจากตำแหน่งหนึ่งstartไปอีกตำแหน่งหนึ่งendด้วยstr
  • reverse()— กลับลำดับของอักขระทั้งหมด
  • substring(int start)- จะส่งคืนสตริงย่อยเริ่มต้นที่ตำแหน่ง start
  • substring(int start, int end)- จะส่งคืนสตริงย่อยโดยเริ่มจากตำแหน่งหนึ่งstartไปอีกตำแหน่งหนึ่งend
รายการวิธีการและตัวสร้างทั้งหมดอยู่ในเอกสารอย่างเป็นทางการ วิธีการข้างต้นทำงานอย่างไร? มาดูในทางปฏิบัติ:
public static void main(String[] args) {
     String numbers = "0123456789";

     StringBuffer sb = new StringBuffer(numbers);

     System.out.println(sb.substring(3)); // 3456789
     System.out.println(sb.substring(4, 8)); // 4567
     System.out.println(sb.replace(3, 5, "ABCDE")); // 012ABCDE56789

     sb = new StringBuffer(numbers);
     System.out.println(sb.reverse()); // 9876543210
     sb.reverse(); // Return the original order

     sb = new StringBuffer(numbers);
     System.out.println(sb.delete(5, 9)); // 012349
     System.out.println(sb.deleteCharAt(1)); // 02349
     System.out.println(sb.insert(1, "One")); // 0One2349
    }

ข้อดี:

  1. ดังที่กล่าวไปแล้ว StringBuffer เป็นคลาสที่ไม่แน่นอน ดังนั้นการทำงานกับคลาสนี้จึงไม่สร้างขยะหน่วยความจำในปริมาณเท่ากันกับคลาส String ดังนั้น หากมีการแก้ไขสตริงจำนวนมาก ควรใช้StringBuffer.

  2. StringBuffer เป็นคลาสที่ปลอดภัยสำหรับเธรด วิธีการของมันถูกซิงโครไนซ์และอินสแตนซ์สามารถใช้งานได้หลายเธรดพร้อมกัน

ข้อบกพร่อง:

ในด้านหนึ่ง ความปลอดภัยของด้ายเป็นข้อได้เปรียบของชั้นเรียน และอีกด้านหนึ่ง ก็เป็นข้อเสีย วิธีการซิงโครไนซ์จะช้ากว่าวิธีที่ไม่ซิงโครไนซ์ นี่คือจุดที่ StringBuilder เข้ามามีบทบาท เรามาดูกันว่าคลาส Java นี้คืออะไร - StringBuilder มีเมธอดใดและฟีเจอร์ของมันคืออะไร

คลาส StringBuilder

StringBuilder ใน Java เป็นคลาสที่แสดงถึงลำดับของอักขระ มันคล้ายกับ StringBuffer มากในทุก ๆ ด้าน ยกเว้นความปลอดภัยของเธรด StringBuilder จัดเตรียม API ที่คล้ายกับของ StringBuffer มาสาธิตสิ่งนี้โดยใช้ตัวอย่างที่คุ้นเคยอยู่แล้ว โดยแทนที่การประกาศตัวแปรจาก StringBufer เป็น StringBuilder:
public static void main(String[] args) {
    String numbers = "0123456789";

    StringBuilder sb = new StringBuilder(numbers);

    System.out.println(sb.substring(3)); //3456789
    System.out.println(sb.substring(4, 8)); //4567
    System.out.println(sb.replace(3, 5, "ABCDE")); //012ABCDE56789

    sb = new StringBuilder(numbers);
    System.out.println(sb.reverse()); //9876543210
    sb.reverse(); // Return the original order

    sb = new StringBuilder(numbers);
    System.out.println(sb.delete(5, 9)); //012349
    System.out.println(sb.deleteCharAt(1)); //02349
    System.out.println(sb.insert(1, "One")); //0One2349
}
ข้อแตกต่างเพียงอย่างเดียวคือ StringBuffer ปลอดภัยสำหรับเธรด และวิธีการทั้งหมดจะถูกซิงโครไนซ์ ในขณะที่ StringBuilder ไม่ใช่ นี่เป็นคุณสมบัติเดียวเท่านั้น StringBuilder ใน Java เร็วกว่า StringBuffer เนื่องจากวิธีการไม่ซิงโครไนซ์ ดังนั้น ในกรณีส่วนใหญ่ ยกเว้นในสภาพแวดล้อมแบบมัลติเธรด ควรใช้ StringBuilder สำหรับโปรแกรม Java จะดีกว่า เราสรุปทุกอย่างไว้ในตารางเปรียบเทียบของทั้งสามคลาส:

String กับ StringBuffer กับ StringBuilder

สตริง StringBuffer StringBuilder
การเปลี่ยนแปลงได้ Immutable(เลขที่) mutable(ใช่) mutable(ใช่)
ความสามารถในการขยาย final(เลขที่) final(เลขที่) final(เลขที่)
ความปลอดภัยของด้าย ใช่ เนื่องจากความไม่เปลี่ยนรูป ใช่เนื่องจากการซิงโครไนซ์ เลขที่
เมื่อจะใช้ เมื่อทำงานกับสตริงที่ไม่ค่อยได้รับการแก้ไข เมื่อทำงานกับสตริงที่จะถูกแก้ไขบ่อยครั้งในสภาพแวดล้อมแบบมัลติเธรด เมื่อทำงานกับสตริงที่จะถูกแก้ไขบ่อยครั้งในสภาพแวดล้อมแบบเธรดเดียว
คุณสามารถศึกษาหัวข้อนี้โดยละเอียดได้ที่ระดับที่สองของภารกิจ Java Multithreading ในหลักสูตร JavaRush:
ความคิดเห็น
TO VIEW ALL COMMENTS OR TO MAKE A COMMENT,
GO TO FULL VERSION