
Java Collectors.teeing: สรุปสตรีมสองมุมในครั้งเดียว
เคยอยากได้ทั้งค่าเฉลี่ยและจำนวนจากลิสต์เดิม แต่ไม่อยากวนสตรีมสองรอบไหม ผมเคย จนได้ลอง Collectors.teeing
ตามAPI Java 21 teeing คือ collector ที่ส่งองค์ประกอบแต่ละตัวเข้า สอง collector ย่อย แล้วรวมผลด้วยฟังก์ชันผสาน คำว่า tee มาจากการแยกท่อสองทาง
ใช้เมื่อไหร่
เหมาะเมื่อต้องการสถิติคู่จากชุดข้อมูลเดียว เช่น ผลรวมกับจำนวน ค่าเฉลี่ยกับค่าสูงสุด หรือสรุปที่ต้องดูสองมุมพร้อมกัน ถ้าสองงานไม่เกี่ยวกับกันเลย การแยกเมธอดอาจอ่านง่ายกว่า
import java.util.List;
import java.util.stream.Collectors;
public class Main {
record AvgAndCount(double average, long count) {}
static AvgAndCount summarize(List<Integer> values) {
return values.stream().collect(
Collectors.teeing(
Collectors.averagingInt(Integer::intValue),
Collectors.counting(),
AvgAndCount::new
)
);
}
public static void main(String[] args) {
AvgAndCount result = summarize(List.of(2, 4, 6, 8));
assert Math.abs(result.average() - 5.0) < 1e-9;
assert result.count() == 4L;
AvgAndCount empty = summarize(List.of());
assert empty.count() == 0L;
}
}
ตัวอย่างใช้ averagingInt คู่กับ counting แล้วห่อเป็น record อ่านง่ายในชั้นโดเมน
ข้อควรจำ
teeing ไม่ได้ทำให้ side effect ใน collector ย่อยหายไป และสตรีมขนานยังต้องคิดเรื่องความถูกต้องของ collector ที่ใช้ ถ้าต้องการสถิติหลายตัวในอ็อบเจ็กต์เดียว บางที summarizingInt / DoubleSummaryStatistics ก็พอโดยไม่ต้อง teeing
Recap
- ใช้
teeingเมื่อต้องสรุปสองมุมจากสตรีมเดียว - รวมผลด้วยฟังก์ชัน/ record ที่ตั้งชื่อธุรกิจชัด
- ทดสอบเคสว่างและเคสค่าปกติ
- อ่านCollectors API ก่อนเลือกสถิติสำเร็จรูป