Java Map.merge: รวม Counter และลบค่าศูนย์ด้วยกฎเดียว
Map.merge รวมเส้นทาง “ยังไม่มี key” กับ “มีค่าเดิมแล้ว” ไว้ใน call เดียว ถ้า remapping function คืน null entry จะถูกลบ จึงเขียน counter ที่ไม่เก็บค่าศูนย์ได้กระชับครับ
import java.util.HashMap;
import java.util.Map;
public class Main {
static void adjust(Map<String, Integer> stock, String sku, int delta) {
stock.merge(sku, delta, (current, change) -> {
int next = current + change;
return next == 0 ? null : next;
});
}
public static void main(String[] args) {
Map<String, Integer> stock = new HashMap<>();
adjust(stock, "mint", 3);
adjust(stock, "mint", -1);
assert stock.equals(Map.of("mint", 2)) : stock;
adjust(stock, "mint", -2);
assert !stock.containsKey("mint") : stock;
}
}
ตัวอย่างนี้ตั้งใจไม่ยอมให้ delta เป็นศูนย์ในระบบจริงควร validate เพิ่ม เพราะ absent key กับค่าเริ่ม 0 อาจทำให้เก็บ entry ศูนย์ได้ และต้องกำหนดว่าจะยอมให้ยอดติดลบหรือไม่
default implementation ของ Map ไม่รับประกัน synchronization แต่ implementation อย่าง ConcurrentHashMap ระบุ atomicity ของ operation เอง อ่าน contract ของชนิด map จริงก่อนใช้แทน transaction โดยเฉพาะเมื่อ update หลาย key พร้อมกัน
Recap
- กำหนดความหมายของ absent, zero และ negative
- จำว่า remapper คืน
nullเท่ากับลบ entry - อย่าคิดว่า
Mapทุกชนิด atomic เหมือนกัน - ใช้ transaction เมื่อ invariant ครอบหลาย key