Java Scanner.tokens: เปลี่ยน token stream เป็น pipeline ที่ปิด resource ชัดเจน
Scanner.tokens() เปิด token ที่ scanner แยกไว้เป็น Stream<String> เราจึงต่อ map, filter และ collector ได้โดยไม่เขียน while loop ครับ แต่ stream ยังผูกกับ scanner และ input เดิม ต้อง consume ภายในช่วงที่ resource เปิดอยู่
import java.util.List;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
try (var scanner = new Scanner("mint, forest, , teal")) {
scanner.useDelimiter("\\s*,\\s*");
List<String> colors = scanner.tokens()
.map(String::trim)
.filter(token -> !token.isEmpty())
.toList();
assert colors.equals(List.of("mint", "forest", "teal"));
}
try (var scanner = new Scanner("")) {
assert scanner.tokens().count() == 0;
}
}
}
Tokenizer เล็ก ไม่ใช่ CSV parser เต็มรูปแบบ
Delimiter regex ไม่เข้าใจ quoted comma, escape และ newline ใน field หากข้อมูลเป็น CSV จริงให้ใช้ parser ที่รองรับมาตรฐาน อย่าขยาย regex จนกลายเป็นร้านข้าวที่พยายามทำบัญชีภาษีด้วยกระดาษจดออเดอร์
Stream ต้องไม่ถูกใช้หลัง scanner ปิด และไม่ควรสร้าง parallel stream จาก scanner ที่อ่าน state ต่อเนื่อง หากต้องประมวลผลขนาน ให้ materialize token ที่ตรวจแล้วก่อน
Recap
- consume stream ภายใน try-with-resources
- กำหนด delimiter ให้ตรง format ง่าย ๆ เท่านั้น
- ใช้ parser เฉพาะทางสำหรับ CSV/grammar จริง
- อย่าใช้ stream หลัง scanner ถูกปิด