Java Collectors.partitioningBy: แบ่ง Stream เป็นสองฝั่งด้วย predicate เดียว
เมื่อรายการหนึ่งต้องแยกเป็น “ผ่าน” กับ “ไม่ผ่าน” การ filter() สองรอบอ่านง่ายแต่เดินข้อมูลซ้ำ Collectors.partitioningBy() เดิน Stream ครั้งเดียวและคืน Map<Boolean, List<T>> ที่มีทั้ง key true และ false
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
public class Main {
static Map<Boolean, List<Integer>> partitionEven(List<Integer> values) {
return values.stream()
.collect(Collectors.partitioningBy(n -> n % 2 == 0));
}
public static void main(String[] args) {
Map<Boolean, List<Integer>> result = partitionEven(List.of(1, 2, 3, 4));
assert result.get(true).equals(List.of(2, 4));
assert result.get(false).equals(List.of(1, 3));
Map<Boolean, List<Integer>> empty = partitionEven(List.of());
assert empty.get(true).isEmpty();
assert empty.get(false).isEmpty();
System.out.println("partitioningBy tests passed");
}
}
ต่างจาก groupingBy อย่างไร
groupingBy() เหมาะกับ key หลายค่า เช่น department หรือ status และ map อาจมีเฉพาะ key ที่พบจริง ส่วน partitioningBy() สื่อชัดว่ามีสองฝั่งตาม predicate และ result มี mapping ทั้งสองค่าแม้ฝั่งหนึ่งว่าง
ถ้าต้องการเพียงรายการที่ผ่าน อย่า partition ทั้งก้อน ใช้ filter() จะใช้หน่วยความจำน้อยกว่า แต่ถ้าต้องส่งทั้ง accepted และ rejected ไปคนละขั้น การ partition ครั้งเดียวทำให้ predicate ไม่ถูกเรียกซ้ำและลดโอกาส logic สองฝั่งไม่ตรงกัน
Recap
- ใช้เมื่อทั้งฝั่ง true และ false มีผู้ใช้ต่อ
- ใช้
filter()เมื่อสนใจฝั่งเดียว - ใช้
groupingBy()เมื่อ key มีมากกว่าสองค่า - เปิด assertion ด้วย
java -eaตอนรันตัวอย่าง