นากกายต้นฉบับแยกริบบิ้นข้อความยาวออกเป็นแถบสั้นหลายบรรทัดบนโต๊ะมิ้นต์

Java String.lines: อ่านข้อความหลายบรรทัดแบบ Stream โดยไม่ทิ้งท้ายด้วยช่องว่างปลอม

พี่โชว์Engineering

การแยกข้อความด้วย split("\\R") เรียก regex engine และมี semantics เรื่องช่องว่างท้ายที่ต้องจำ String.lines() คืน lazy Stream<String> สำหรับบรรทัดที่คั่นด้วย \n, \r หรือ \r\n และไม่สร้างบรรทัดว่างเพิ่มเพียงเพราะข้อความจบด้วย line terminator

import java.util.List;

public class Main {
    static List<String> nonBlankLines(String text) {
        return text.lines()
                .map(String::strip)
                .filter(line -> !line.isEmpty())
                .toList();
    }

    public static void main(String[] args) {
        String mixed = " first\r\n\r\nsecond \n";
        assert nonBlankLines(mixed).equals(List.of("first", "second"));
        assert "".lines().count() == 0;
        assert "one\n".lines().toList().equals(List.of("one"));
        System.out.println("String.lines tests passed");
    }
}

เมื่อไหร่ยังต้องใช้วิธีอื่น

lines() เหมาะกับ text processing ที่นิยามบรรทัดแบบ Java แต่ไม่ได้คืนตัวคั่น หากต้องรักษา newline เดิมเพื่อ formatter หรือ patch tool ให้ parser เก็บ delimiter เอง และถ้าต้องอ่านไฟล์ใหญ่ อย่าโหลดทั้งหมดมาเป็น String ก่อน ใช้ Files.lines(path) ภายใน try-with-resources เพื่อปิดไฟล์ให้แน่นอน

Stream นี้ lazy ในระดับการแยกบรรทัดของ String ที่อยู่ในหน่วยความจำแล้ว จึงช่วยลด array ชั่วคราวจาก split() แต่ไม่ได้ทำให้ String ต้นทางเล็กลง

Recap

  • ใช้ String.lines() เมื่อมี String อยู่แล้วและต้อง process เป็น Stream
  • จำว่า newline ท้ายสุดไม่สร้างบรรทัดว่างเพิ่ม
  • ใช้ Files.lines() สำหรับไฟล์ใหญ่และปิด resource
  • ใช้ parser อื่นเมื่อจำเป็นต้องรักษาตัวคั่นเดิม