รับพนักงานก่อนและหลังวันที่เฉพาะเจาะจงของการเข้าร่วมจากรายชื่อพนักงานที่มีสตรีม Java


9

ฉันมีListของEmployees กับวันที่มาร่วมงานที่แตกต่างกัน ฉันต้องการรับพนักงานก่อนและหลังวันที่เฉพาะเจาะจงของการเข้าร่วมจากรายการโดยใช้สตรีม

ฉันลองรหัสต่อไปนี้

 List<Employee> employeeListAfter = employeeList.stream()
                .filter(e -> e.joiningDate.isAfter(specificDate))
                .collect(Collectors.toList());

List<Employee> employeeListBefore = employeeList.stream()
        .filter(e -> e.joiningDate.isBefore(specificDate))
        .collect(Collectors.toList());

class Employee{
    int id;
    String name;
    LocalDate joiningDate;
}

มีวิธีการทำเช่นนี้ในกระแสเดียว?


1
คุณสามารถใช้partitioningBy
Code_Mode

5
ก่อนและหลัง - ดังนั้นคุณต้องการพนักงานทุกคนยกเว้นผู้ที่เข้าร่วมในวันที่?
John3136

สมมติว่าเป็น "เป็นพนักงานอย่างน้อยตั้งแต่" คุณจะต้องแยกก่อนและไม่ก่อนไม่สนใจเลย
JollyJoker

คำตอบ:


16

คุณสามารถใช้partitioningByดังต่อไปนี้

Map<Boolean, List<Employee>> listMap = employeeList.stream()
        .collect(Collectors.partitioningBy(e -> e.joiningDate.isAfter(specificDate)));

List<Employee> employeeListAfter = listMap.get(true);
List<Employee> employeeListBefore = listMap.get(false);

partitioningByส่งคืน Collector ซึ่งแบ่งพาร์ติชันอิลิเมนต์อินพุตตาม Predicate และจัดระเบียบพวกมันเป็นMap<Boolean, List<T>>

specificDateหมายเหตุว่านี้จะไม่จัดการกับพนักงานที่มี


1
คำอธิบายของรหัสจะดีมาก
Vishwa Ratna

2
สิ่งนี้ไม่ได้ทำในสิ่งที่รหัสในคำถาม - พนักงานที่มีspecificDateที่ดินจะfalseแบ่งพาร์ติชันในรหัสที่ไม่มีคำถาม
Andronicus

การเพิ่มวิธีspecificDate.plusDays(1)แก้ไขปัญหาได้อย่างไร specificDateจะยังคงอยู่ในfalseส่วน
Andronicus

จากนั้นมันจะอยู่ในtrueพาร์ติชั่น ...
Andronicus

1
@Andronicus: OP เท่านั้นที่รู้ว่าพฤติกรรมนี้เป็นข้อบกพร่องหรือคุณสมบัติ สำหรับฉันดูเหมือนปลอดภัยกว่าที่จะไม่ปล่อยให้พนักงานคนใดออกไป
Eric Duminil

9

หากรายการของคุณสามารถมีรายการที่เข้าร่วมในspecificDateแล้วคุณอาจพบว่าgroupingByมีประโยชน์:

Map<Integer, List<Employee>> result = employeeList.stream()
    .map(emp -> new AbstractMap.SimpleEntry<>(specificDate.compareTo(emp.getJoiningDate()), emp))
    .collect(Collectors.groupingBy(entry -> entry.getKey() > 0 ? 1 : (entry.getKey() < 0 ? -1 : 0),
            Collectors.mapping(entry -> entry.getValue(), Collectors.toList())));

employeeListAfter = result.get(-1);
employeeListBefore = result.get(1);
employeeListOnSpecificDate = result.get(0);

resultแผนที่มีEmployeeการบันทึกจัดกลุ่มตามตำแหน่งที่ค่อนข้างไปspecificDateเพื่อให้คุณสามารถเลือกที่เข้าร่วมก่อนหลังหรือในวันที่ที่ระบุ


นี่ควรเป็นคำตอบที่ได้รับการยอมรับ
Andronicus

2
-1 คุณกำลังทำการสันนิษฐานเท็จว่าcompareToจะคืนค่า -1, 0 หรือ 1 เท่านั้นอันที่จริง LocalDate.compareTo สามารถคืนค่า int ใด ๆ
MikeFHay

1
@ MikeFHay ขอบคุณที่ชี้ให้เห็น ฉันทำการทดสอบอย่างรวดเร็วมากและข้ามไปยังข้อสรุป เปลี่ยนการใช้งาน (และทันใดนั้นมันก็ดูซับซ้อน)
ernest_k

2
@ernest_k: คุณสามารถใช้ต้นฉบับcompareToและโทรหาInteger.signumมันได้
Eric Duminil

1
@JollyJoker ในกรณีที่คุณไม่ได้รู้ว่าคุณสามารถเชื่อมโยงไปยังบรรทัดที่เฉพาะเจาะจงใน GitHub: เช่นนี้ การคลิกที่หมายเลขบรรทัดจะเป็นการเปลี่ยน URL โดยตรง คุณสามารถเพิกเฉยหากคุณรู้หรือไม่สนใจ ;)
Eric Duminil

4

คุณต้องกรองพนักงานด้วยวันที่นี้ จากนั้นคุณสามารถใช้การแบ่งพาร์ติชัน:

Map<Boolean, List<Employee>> partitioned = employeeList.stream()
    .filter(e -> !e.joiningDate.equals(specificDate))
    .collect(partitioningBy(e -> e.joiningDate.isAfter(specificDate)));

List<Employee> employeeListAfter = partitioned.get(true);
List<Employee> employeeListBefore = partitioned.get(false);

สิ่งนี้จะสร้างแผนที่ของคอลเลกชันขึ้นอยู่กับว่าพวกเขาตอบสนองกริยา


เรียนรู้partitioningBy วันนี้
Vishwa Ratna

ไม่คุณไม่สามารถกรองด้วยวันที่เพราะมันจะกรองพนักงานที่มีเฉพาะวันที่
Code_Mode

@Code_Mode โอ้ใช่ฉันพลาดไปแล้วขอบคุณ!
Andronicus

2

คุณสามารถใช้Collectors.groupingByและใช้compareToวิธีการจัดกลุ่มรายชื่อพนักงานตามวันที่ก่อนหน้าปัจจุบันและอนาคต

Map<Integer, List<Employee>> result = employeeList.stream()
            .collect(Collectors.groupingBy(e-> e.joiningDate.compareTo(specificDate)< 0 ? -1 : (e.joiningDate.compareTo(specificDate) == 0 ? 0 : 1)));

ดังนั้นผลลัพธ์จะเป็น

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.