ความแตกต่างระหว่างเมธอด String trim () และ strip () ใน Java 11


104

ท่ามกลางการเปลี่ยนแปลงอื่น ๆ JDK 11 แนะนำ 6 เมธอดใหม่สำหรับคลาส java.lang.String:

  • repeat(int)- ทำซ้ำ String หลาย ๆ ครั้งตามที่intพารามิเตอร์กำหนด
  • lines() - ใช้ Spliterator เพื่อให้เส้นจากสตริงต้นทางอย่างเกียจคร้าน
  • isBlank() - ระบุว่าสตริงว่างหรือมีเฉพาะอักขระช่องว่าง
  • stripLeading() - ลบพื้นที่สีขาวออกจากจุดเริ่มต้น
  • stripTrailing() - ลบพื้นที่สีขาวออกจากส่วนท้าย
  • strip() - ลบช่องว่างสีขาวจากทั้งสองจุดเริ่มต้นและจุดสิ้นสุดของสตริง

โดยเฉพาะอย่างยิ่งลักษณะคล้ายกับstrip() trim()ตามวิธีการของบทความนี้ strip*()ออกแบบมาเพื่อ:

วิธี String.strip (), String.stripLeading () และ String.stripTrailing () ตัดช่องว่างสีขาว [ตามที่กำหนดโดย Character.isWhiteSpace ()] ทั้งด้านหน้าด้านหลังหรือทั้งด้านหน้าและด้านหลังของสตริงเป้าหมาย

String.trim() สถานะ JavaDoc:

/**
  * Returns a string whose value is this string, with any leading and trailing
  * whitespace removed.
  * ...
  */

ซึ่งเกือบจะเหมือนกับคำกล่าวข้างต้น

อะไรคือความแตกต่างระหว่างString.trim()และString.strip()ตั้งแต่ Java 11?

คำตอบ:


106

ในระยะสั้น: strip()คือ "Unicode ตระหนักถึง" trim()วิวัฒนาการของ

CSR: JDK-8200378

ปัญหา

String :: trim มีมาตั้งแต่ยุคแรก ๆ ของ Java เมื่อ Unicode ยังไม่ได้พัฒนาไปสู่มาตรฐานที่เราใช้กันอย่างแพร่หลายในปัจจุบัน

คำจำกัดความของช่องว่างที่ใช้โดย String :: trim คือจุดรหัสใด ๆ ที่น้อยกว่าหรือเท่ากับจุดรหัสพื้นที่ (\ u0020) ซึ่งโดยทั่วไปเรียกว่าอักขระควบคุม ASCII หรือ ISO

รูทีนการตัดแต่ง Unicode-Aware ควรใช้ Character :: isWhitespace (int)

นอกจากนี้นักพัฒนายังไม่สามารถลบช่องว่างการเยื้องออกโดยเฉพาะหรือเพื่อลบพื้นที่สีขาวต่อท้ายโดยเฉพาะ

สารละลาย

แนะนำวิธีการตัดแต่งที่ตระหนักถึงพื้นที่สีขาว Unicode และให้การควบคุมเพิ่มเติมเฉพาะส่วนนำหน้าหรือต่อท้ายเท่านั้น

ลักษณะทั่วไปของวิธีการใหม่เหล่านี้เป็นสิ่งที่พวกเขาใช้ที่แตกต่างกัน (ใหม่) ความหมายของ "ช่องว่าง" กว่าวิธีเก่า ๆ String.trim()เช่น Bug JDK-8200373

JavaDoc ปัจจุบันสำหรับ String :: trim ไม่ได้ระบุคำจำกัดความของ "space" ที่ใช้ในโค้ดอย่างชัดเจน ด้วยวิธีการตัดแต่งเพิ่มเติมที่จะมาในอนาคตอันใกล้ซึ่งใช้คำจำกัดความของพื้นที่ที่แตกต่างกันการชี้แจงจึงมีความจำเป็น String :: trim ใช้นิยามของช่องว่างเป็นจุดรหัสใด ๆ ที่น้อยกว่าหรือเท่ากับจุดรหัสอักขระช่องว่าง (\ u0020.) วิธีการตัดแต่งที่ใหม่กว่าจะใช้คำจำกัดความของช่องว่าง (สีขาว) เป็นจุดรหัสใด ๆ ที่ส่งกลับจริงเมื่อส่งผ่านไปยัง อักขระ :: isWhitespace เพรดิเคต

isWhitespace(char)เพิ่มเมธอดCharacterด้วย JDK 1.1 แต่เมธอดisWhitespace(int)ไม่ได้ถูกนำมาใช้กับCharacterคลาสจนกระทั่ง JDK 1.5 วิธีหลัง (วิธีที่ยอมรับพารามิเตอร์ประเภทint) ถูกเพิ่มเพื่อรองรับอักขระเสริม ข้อคิดเห็น Javadoc สำหรับCharacterคลาสกำหนดอักขระเสริม (โดยทั่วไปจะจำลองด้วย "จุดรหัส" ที่อิงตาม int) เทียบกับอักขระ BMP (โดยทั่วไปจะจำลองด้วยอักขระเดี่ยว):

ชุดอักขระจาก U + 0000 ถึง U + FFFF บางครั้งเรียกว่า Basic Multilingual Plane (BMP) อักขระที่มีจุดรหัสมากกว่า U + FFFF เรียกว่าอักขระเสริม แพลตฟอร์ม Java ใช้การแสดง UTF-16 ในอาร์เรย์ถ่านและในคลาส String และ StringBuffer ในการแทนค่านี้อักขระเสริมจะแสดงเป็นคู่ของค่าถ่าน ... ดังนั้นค่าถ่านจึงแสดงถึงจุดรหัส Basic Multilingual Plane (BMP) รวมถึงจุดรหัสตัวแทนหรือหน่วยรหัสของการเข้ารหัส UTF-16 ค่า int แสดงถึงจุดรหัส Unicode ทั้งหมดรวมถึงจุดรหัสเสริม ... วิธีการที่ยอมรับเฉพาะค่าถ่านไม่สามารถรองรับอักขระเสริมได้ ... เมธอดที่ยอมรับค่า int สนับสนุนอักขระ Unicode ทั้งหมดรวมถึงอักขระเสริม

OpenJDK แก้ไข


การเปรียบเทียบเกณฑ์มาตรฐานระหว่างtrim()และstrip()- เหตุใด String.strip () จึงเร็วกว่า String.trim () ถึง 5 เท่าสำหรับสตริงว่างใน Java 11


6
ที่น่าสนใจคือสัญลักษณ์ "\ u0000" ไม่ได้ถูกลบด้วยแถบ แต่ถูกลบโดยการตัดแต่ง
CHEM_Eugene

32

นี่คือการทดสอบหน่วยที่แสดงคำตอบโดย @MikhailKholodkov โดยใช้ Java 11

(โปรดทราบว่า\u2000อยู่ด้านบน\u0020และไม่ถือเป็นช่องว่างtrim())

public class StringTestCase {
    @Test
    public void testSame() {
        String s = "\t abc \n";

        assertEquals("abc", s.trim());
        assertEquals("abc", s.strip());
    }

    @Test
    public void testDifferent() {
        Character c = '\u2000';
        String s = c + "abc" + c;

        assertTrue(Character.isWhitespace(c));
        assertEquals(s, s.trim());
        assertEquals("abc", s.strip());
    }
}

0

โดยทั่วไปทั้งสองวิธีจะลบช่องว่างนำหน้าและต่อท้ายออกจากสตริง อย่างไรก็ตามความแตกต่างเกิดขึ้นเมื่อเราทำงานกับตัวอักษร Unicode หรือคุณสมบัติหลายภาษา

trim () ลบอักขระนำหน้าและต่อท้ายทั้งหมดที่มีค่า ASCII น้อยกว่าหรือเท่ากับ 32 ('U + 0020' หรือช่องว่าง)

ตามมาตรฐาน Unicode มีอักขระช่องว่างต่างๆที่มีค่า ASCII มากกว่า 32 ('U + 0020') เช่น 8193 (U + 2001)

ในการระบุอักขระช่องว่างเหล่านี้เมธอดใหม่ isWhitespace (int) ถูกเพิ่มจาก Java 1.5 ในคลาส Character วิธีนี้ใช้ Unicode เพื่อระบุอักขระช่องว่าง คุณสามารถอ่านเพิ่มเติมเกี่ยวกับอักขระช่องว่าง Unicode ได้ที่นี่ที่นี่

แถบเมธอดใหม่ที่เพิ่มเข้ามาใน java 11 ใช้เมธอด Character.isWhitespace (int) นี้เพื่อครอบคลุมอักขระช่องว่างที่หลากหลายและลบ

ตัวอย่าง

public class StringTrimVsStripTest {
    public static void main(String[] args) {
        String string = '\u2001'+"String    with    space"+ '\u2001';
        System.out.println("Before: \"" + string+"\"");
        System.out.println("After trim: \"" + string.trim()+"\"");
        System.out.println("After strip: \"" + string.strip()+"\"");
   }
}

เอาต์พุต

Before: "  String    with    space  "
After trim: " String    with    space "
After strip: "String    with    space"

หมายเหตุ:หากคุณใช้งานบนเครื่อง windows คุณอาจไม่สามารถเห็นผลลัพธ์ที่คล้ายกันได้เนื่องจากการตั้งค่า Unicode ที่ จำกัด คุณสามารถลองใช้คอมไพเลอร์ออนไลน์เพื่อทดสอบโค้ดนี้ได้

อ้างอิง: ความแตกต่างระหว่าง java วิธีการตัดและแถบ

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