นากกายตรวจช่องเก็บของและหยิบตะกร้าสำรองเมื่อช่องไม่มีอยู่โดยไม่สร้างช่องใหม่

Java Map.getOrDefault: อ่าน fallback โดยไม่เผลอเพิ่ม key

พี่โชว์Engineering

เวลาอ่าน config เรามักต้องการ fallback ชั่วคราว แต่ไม่ต้องการแก้ map Map.getOrDefault คืนค่าที่มีหรือ default โดยไม่ insert key ใหม่ ต่างจาก computeIfAbsent ที่อาจแก้โครงสร้างครับ

WHY: หยิบตะกร้าสำรอง ไม่ได้สร้างล็อกเกอร์ใหม่

ถ้าช่องเก็บของไม่มี getOrDefault แค่ยื่นตะกร้าสำรองให้ผู้เรียก หลังจบ lookup แผนผังช่องยังเหมือนเดิม เหมาะกับการ render, validation หรือ calculation ที่ต้องอ่านค่า แต่ไม่ควรเปลี่ยน source of truth เป็นผลข้างเคียง

import java.util.HashMap;
import java.util.Map;

public class Main {
    public static void main(String[] args) {
        Map<String, String> config = new HashMap<>();
        config.put("mode", "safe");
        config.put("label", null);

        assert config.getOrDefault("mode", "standard").equals("safe");
        assert config.getOrDefault("missing", "standard").equals("standard");
        assert !config.containsKey("missing");

        assert config.containsKey("label");
        assert config.getOrDefault("label", "untitled") == null;
        System.out.println("map fallback verified");
    }
}

HOW: key ที่ map ไป null ยังถือว่ามีอยู่

จุดที่พลาดบ่อยคือคิดว่า default จะถูกใช้เมื่อ get() คืน null แต่ contract แยก missing key จาก key ที่มีค่า null ดังนั้นตัวอย่าง label คืน null ไม่ใช่ untitled หากโดเมนไม่ต้องการสามสถานะ ควรห้าม null ใน map ด้วยการ validate ตอนรับข้อมูล หรือใช้ immutable factory ที่ปฏิเสธ null

ถ้าต้องการคำนวณแล้วจำ fallback ลง map ใช้ computeIfAbsent โดยเข้าใจ concurrency และ side effect ของ mapping function ส่วน default ที่สร้างแพงจะถูกประเมินก่อนเรียก getOrDefault; ย้ายการสร้างออกเป็น supplier ของ logic เองเมื่อจำเป็น

Recap

  • ใช้ getOrDefault สำหรับ lookup ที่ไม่แก้ map
  • ตรวจ containsKey เมื่อ null กับ missing มีความหมายต่างกัน
  • ห้าม null ตั้งแต่ boundary หากโดเมนมีเพียงสองสถานะ
  • ใช้ computeIfAbsent เมื่ออยากบันทึกค่าที่คำนวณจริง ๆ
  • อย่าสร้าง default ราคาแพงโดยไม่จำเป็น