Java OptionalInt.stream: ต่อค่าที่อาจไม่มีเข้ากับ IntStream
ฟังก์ชัน parse ที่คืน OptionalInt บอกได้ชัดว่ามีค่าหรือไม่มี โดยไม่ต้องใช้ -1 เป็น sentinel เมื่อต้องต่อหลายผลเข้ากับ pipeline OptionalInt.stream() เปลี่ยนแต่ละผลเป็น IntStream ที่มีศูนย์หรือหนึ่งสมาชิกครับ
import java.util.List;
import java.util.OptionalInt;
public class Main {
static OptionalInt parsePort(String raw) {
try {
int port = Integer.parseInt(raw);
return port >= 1 && port <= 65535 ? OptionalInt.of(port) : OptionalInt.empty();
} catch (NumberFormatException ignored) {
return OptionalInt.empty();
}
}
public static void main(String[] args) {
int[] ports = List.of("443", "bad", "0", "8080").stream()
.flatMapToInt(raw -> parsePort(raw).stream())
.toArray();
assert java.util.Arrays.equals(ports, new int[] {443, 8080});
}
}
ภาพเปรียบเทียบคือประตูตรวจตั๋ว: ค่าที่ผ่านเงื่อนไขปล่อยลูกปัดหนึ่งเม็ดเข้าสายพาน ส่วนค่าที่ว่างไม่มีเม็ดออกมาเลย วิธีนี้รักษา primitive stream จึงไม่ต้องเปลี่ยนเป็น Optional<Integer> แล้ว boxing/unboxing ในทางเดินหลัก
แต่การทิ้งค่าที่ parse ไม่ผ่านทำให้เหตุผลหาย ถ้าต้องรายงานว่า input ไหนผิดและเพราะอะไร ให้คืน result type ที่มี error หรือเก็บ validation report แยก ไม่ควรใช้ Optional เป็นถังซ่อน exception
Recap
- ใช้
OptionalInt.streamสำหรับผลแบบศูนย์หรือหนึ่งค่า - รักษา primitive pipeline ด้วย
flatMapToInt - อย่าใช้ sentinel ที่ชนกับค่าจริงได้
- ใช้ result/error type เมื่อผู้ใช้ต้องรู้สาเหตุที่ parse ไม่ผ่าน