Java Optional.stream: แบนค่าที่อาจหายโดยไม่แตก pipeline เป็น if
เมื่อ lookup หลายค่าแล้วแต่ละผลเป็น Optional<T> เรามักเห็น filter(Optional::isPresent) ตามด้วย map(Optional::get) ซึ่งทำงานได้แต่แยกกฎเดียวเป็นสองขั้น Optional.stream คืน stream หนึ่งสมาชิกเมื่อมีค่า และ stream ว่างเมื่อไม่มี จึงต่อกับ flatMap ได้ตรงความหมายครับ
import java.util.List;
import java.util.Map;
import java.util.Optional;
public class Main {
static List<String> resolve(Map<String, String> users, List<String> ids) {
return ids.stream()
.map(id -> Optional.ofNullable(users.get(id)))
.flatMap(Optional::stream)
.toList();
}
public static void main(String[] args) {
Map<String, String> users = Map.of("a", "Anan", "c", "Chaba");
assert resolve(users, List.of("a", "b", "c"))
.equals(List.of("Anan", "Chaba"));
assert resolve(users, List.of("missing")).isEmpty();
System.out.println("Optional.stream tests passed");
}
}
เทคนิคนี้ดีเมื่อ “ไม่พบ” เป็นผลปกติที่ตัดออกได้ ถ้าทุก ID ต้องมีข้อมูล การแบน Optional จะซ่อนปัญหาและทำให้จำนวนผลไม่ตรง input ควรเปลี่ยนเป็น error ที่ระบุ ID หายหรือ validation ก่อนเริ่ม pipeline อีกอย่าง Optional ไม่ควรใช้แทน collection; ถ้ามีหลายค่าอยู่แล้วคืน Stream<T> หรือ List<T> ให้ตรงชนิด
Recap
- ใช้
flatMap(Optional::stream)เมื่อค่าที่หายตัดออกได้ - อย่าซ่อน missing record ที่เป็น invariant violation
- ใช้ Optional กับศูนย์หรือหนึ่งค่าเท่านั้น
- ทดสอบลำดับผลและกรณีหายทั้งหมด