ฉันชอบความคิดของ StringTokenizer เพราะมันนับได้
แต่มันก็ล้าสมัยและแทนที่ด้วย String.split ซึ่งส่งคืนสตริงที่น่าเบื่อ [] (และไม่รวมถึงตัวคั่น)
ดังนั้นฉันจึงใช้ StringTokenizerEx ซึ่งเป็น Iterable และ regexp ที่แท้จริงในการแบ่งสตริง
regexp ที่แท้จริงหมายความว่าไม่ใช่ 'ลำดับอักขระ' ซ้ำเพื่อสร้างตัวคั่น:
'o' จะจับคู่เฉพาะ 'o' และแยก 'ooo' เป็นสามตัวคั่นโดยมีสตริงว่างสองตัวอยู่ภายใน:
[o], '', [o], '', [o]
แต่ regexp o + จะส่งคืนผลลัพธ์ที่คาดหวังเมื่อแยก "aooob"
[], 'a', [ooo], 'b', []
วิธีใช้ StringTokenizerEx นี้:
final StringTokenizerEx aStringTokenizerEx = new StringTokenizerEx("boo:and:foo", "o+");
final String firstDelimiter = aStringTokenizerEx.getDelimiter();
for(String aString: aStringTokenizerEx )
{
// uses the split String detected and memorized in 'aString'
final nextDelimiter = aStringTokenizerEx.getDelimiter();
}
รหัสของคลาสนี้มีให้ที่DZone Snippetsเกร็ดเล็กเกร็ดน้อย
ตามปกติสำหรับรหัสความท้าทายการตอบสนอง (ชั้นหนึ่งตนเองมีกรณีทดสอบรวม), การคัดลอกวาง (ใน 'src / test' directory) และเรียกใช้ วิธีการหลัก () แสดงให้เห็นถึงประเพณีที่แตกต่างกัน
หมายเหตุ: (แก้ไขปลายปี 2009)
บทความสุดท้ายความคิด: Java ปริศนา: แยกขนString.split()ไม่ได้ทำงานที่ดีการอธิบายพฤติกรรมที่แปลกประหลาดใน
Josh Bloch แสดงความคิดเห็นในการตอบสนองต่อบทความนั้น:
ใช่นี่เป็นความเจ็บปวด FWIW ทำด้วยเหตุผลที่ดีมาก: ใช้งานร่วมกับ Perl ได้
คนที่ทำเช่นนั้นคือ Mike "madbot" McCloskey ซึ่งตอนนี้ทำงานร่วมกับเราที่ Google Mike ทำให้แน่ใจว่านิพจน์ทั่วไปของ Java ผ่านการทดสอบนิพจน์ปกติ 30K Perl ทุก ๆ อัน (และวิ่งเร็วขึ้น)
Guava ไลบรารีทั่วไปของ Google มีตัวแยกซึ่งก็คือ:
- ใช้ง่ายกว่า
- ดูแลโดย Google (ไม่ใช่คุณ)
ดังนั้นจึงอาจคุ้มค่าที่จะเช็คเอาท์ จากเอกสารคร่าวๆเริ่มต้นของพวกเขา(pdf) :
JDK มีสิ่งนี้:
String[] pieces = "foo.bar".split("\\.");
มันเป็นเรื่องดีที่จะใช้สิ่งนี้หากคุณต้องการสิ่งที่มันทำ: - การแสดงออกปกติ - ผลเป็นอาร์เรย์ - วิธีการจัดการชิ้นส่วนที่ว่างเปล่า
Mini-puzzler: ", a ,, b,". split (",") ส่งคืน ...
(a) "", "a", "", "b", ""
(b) null, "a", null, "b", null
(c) "a", null, "b"
(d) "a", "b"
(e) None of the above
คำตอบ: (e) ไม่มีข้อใดข้างต้น
",a,,b,".split(",")
returns
"", "a", "", "b"
มีเพียงเทขยะต่อท้ายเท่านั้นที่ข้ามไป! (ใครจะรู้วิธีแก้ปัญหาเพื่อป้องกันการกระโดดข้าม? มันเป็นเกมที่สนุก ... )
ไม่ว่าในกรณีใดตัวแยกสัญญาณของเรานั้นมีความยืดหยุ่นมากกว่า: พฤติกรรมเริ่มต้นนั้นง่าย:
Splitter.on(',').split(" foo, ,bar, quux,")
--> [" foo", " ", "bar", " quux", ""]
หากคุณต้องการคุณสมบัติพิเศษถามพวกเขา!
Splitter.on(',')
.trimResults()
.omitEmptyStrings()
.split(" foo, ,bar, quux,")
--> ["foo", "bar", "quux"]
ลำดับของวิธีการตั้งค่าไม่สำคัญ - ในระหว่างการแยกการตัดจะเกิดขึ้นก่อนที่จะตรวจสอบหาสิ่งที่ว่างเปล่า