Nhận nhân viên trước và sau ngày tham gia cụ thể từ Danh sách nhân viên với luồng Java


9

Tôi có Listcủa Employees với số ngày tham gia khác nhau. Tôi muốn nhận Nhân viên trước và sau ngày tham gia cụ thể từ Danh sách bằng cách sử dụng luồng.

tôi đã thử mã

 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;
}

Có cách nào để làm điều này trong một luồng không?


1
Bạn có thể sử dụngpartitioningBy
Code_Mode

5
Trước và sau - vì vậy bạn muốn tất cả nhân viên ngoại trừ những người tham gia vào ngày này?
John3136

Giả sử "ít nhất là một nhân viên", bạn sẽ muốn tách ra trước và không trước, không quan tâm đến tất cả.
JollyJoker

Câu trả lời:


16

Bạn có thể sử dụng partitioningBynhư dưới đây,

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);

phân vùngBy Trả về Collector, phân vùng các phần tử đầu vào theo Vị ngữ và sắp xếp chúng thành mộtMap<Boolean, List<T>>

Lưu ý rằng điều này sẽ không xử lý nhân viên với specificDate.


1
Một lời giải thích về mã sẽ là tuyệt vời.
Vishwa Ratna

2
Điều này không thực hiện chính xác, những gì mã được đề cập sẽ làm - nhân viên với specificDatesẽ falserơi vào phân vùng, trong đó không có mã nào được đề cập
Andronicus

Làm thế nào để thêm specificDate.plusDays(1)giải quyết vấn đề? specificDatevẫn sẽ ở trong falsemột phần.
Andronicus

Sau đó, nó sẽ nằm trong truephân vùng ...
Andronicus

1
@Andronicus: Chỉ OP biết hành vi này là lỗi hay tính năng. Đối với tôi, có vẻ an toàn hơn khi không để bất kỳ nhân viên nào ra ngoài.
Eric Duminil

9

Nếu danh sách của bạn có thể có các mục được tham gia trênspecificDate , thì bạn có thể thấy groupingByhữu ích:

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);

Các resultbản đồ chứa Employeehồ sơ được phân nhóm theo vị trí tương đối để specificDate, vì vậy bạn có thể chọn người tham gia trước, sau, hoặc vào ngày quy định.


Đây phải là câu trả lời được chấp nhận
Andronicus

2
-1. Bạn đang đưa ra giả định sai compareTosẽ chỉ trả về -1, 0 hoặc 1. Trong thực tế LocalDate.compareTo có thể trả về bất kỳ int nào.
MikeFHay

1
@MikeFHay Cảm ơn bạn đã chỉ ra điều đó. Tôi đã làm một bài kiểm tra rất nhanh và nhảy đến kết luận. Thay đổi thực hiện (và đột nhiên nó trông phức tạp).
ernest_k

2
@ernest_k: Bạn có thể sử dụng bản gốc compareTovà gọi Integer.signumnó.
Eric Duminil

1
@JollyJoker Chỉ trong trường hợp bạn không biết, bạn có thể liên kết đến một dòng cụ thể trong github: như thế này . Nhấp vào số dòng thay đổi URL trực tiếp. Hãy bỏ qua nếu bạn đã biết hoặc không quan tâm. ;)
Eric Duminil

4

Bạn cần lọc nhân viên với ngày đặc biệt này. Sau đó, bạn có thể sử dụng phân vùng:

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);

Điều này sẽ tạo ra một bản đồ của các bộ sưu tập dựa trên nếu chúng hoàn thành vị ngữ.


Đã học partitioningBy hôm nay.
Vishwa Ratna

Không, bạn không thể lọc theo ngày vì nó sẽ lọc nhân viên chỉ với ngày cụ thể
Code_Mode

@Code_Mode oh, vâng, tôi đã bỏ lỡ điều đó, cảm ơn bạn!
Andronicus

2

Bạn có thể sử dụng Collectors.groupingByvà sử dụng compareTophương pháp để nhóm danh sách nhân viên dựa trên ngày trước, hiện tại và tương lai

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

Vì vậy, đầu ra sẽ là

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.