Dapatkan Karyawan sebelum dan sesudah tanggal tertentu bergabung dari Daftar Karyawan dengan aliran Java

9

Saya harus Listdari Employees dengan tanggal bergabung berbeda. Saya ingin Mendapatkan Karyawan sebelum dan setelah tanggal tertentu bergabung dari Daftar menggunakan aliran.

saya mencoba kode berikut,

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

Apakah ada cara untuk melakukan ini dalam satu aliran?

Rajiv
sumber
1
Anda dapat menggunakanpartitioningBy
Code_Mode
5
Sebelum dan sesudah - jadi Anda ingin semua karyawan kecuali mereka yang bergabung pada tanggal tersebut?
John3136
Dengan asumsi bahwa "setidaknya sudah menjadi karyawan", Anda pasti ingin berpisah sebelum dan tidak sebelumnya, sama sekali tidak peduli sama sekali.
JollyJoker

Jawaban:

16

Anda dapat menggunakan partitioningByseperti di bawah ini,

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

partisiing Dengan Mengembalikan Kolektor yang mempartisi elemen input sesuai dengan Predikat, dan mengaturnya menjadi aMap<Boolean, List<T>>

Perhatikan bahwa ini tidak akan menangani karyawan specificDate.

Code_Mode
sumber
1
Penjelasan kode akan sangat bagus.
Vishwa Ratna
2
Ini tidak melakukan persis apa yang dilakukan kode - karyawan dengan specificDateakan mendarat di falsepartisi, di mana dalam kode tersebut tidak ada
Andronicus
Bagaimana cara menambahkan specificDate.plusDays(1)menyelesaikan masalah? specificDateakan tetap di falsebagian.
Andronicus
Maka akan berada di truepartisi ...
Andronicus
1
@Andronicus: Hanya OP yang tahu apakah perilaku ini bug atau fitur. Bagi saya, tampaknya lebih aman untuk tidak meninggalkan karyawan.
Eric Duminil
9

Jika daftar Anda dapat memiliki entri yang bergabung padaspecificDate , maka Anda mungkin menemukan groupingByberguna:

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

The resultpeta berisi Employeecatatan dikelompokkan berdasarkan posisi relatif untuk specificDate, sehingga Anda dapat memilih yang bergabung sebelum, sesudah, atau pada tanggal yang ditentukan.

ernest_k
sumber
Ini harus menjadi jawaban yang diterima
Andronicus
2
-1. Anda membuat asumsi salah yang compareTohanya akan mengembalikan -1, 0, atau 1. Faktanya LocalDate.compareTo dapat mengembalikan int apa pun.
MikeFHay
1
@ MikeFHay Terima kasih telah menunjukkannya. Saya melakukan tes yang sangat cepat dan melompat ke kesimpulan. Perubahan implementasi (dan tiba-tiba terlihat rumit).
ernest_k
2
@ernest_k: Anda bisa menggunakan yang asli compareTodan memanggilnya Integer.signum.
Eric Duminil
1
@JollyJoker Kalau-kalau Anda tidak tahu, Anda dapat menautkan ke baris tertentu di github: seperti ini . Mengklik nomor baris akan mengubah URL secara langsung. Jangan ragu untuk mengabaikan jika Anda sudah tahu atau tidak peduli. ;)
Eric Duminil
4

Anda perlu menyaring karyawan dengan tanggal khusus ini. Kemudian Anda dapat menggunakan partisi:

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

Ini akan membuat peta koleksi berdasarkan jika mereka memenuhi predikat.

Andronicus
sumber
Belajar partitioningBy hari ini.
Vishwa Ratna
Tidak, Anda tidak dapat memfilter dengan tanggal karena akan memfilter karyawan dengan hanya tanggal khusus
Code_Mode
@ Kode_Mode oh, ya, saya melewatkannya, terima kasih!
Andronicus
2

Anda dapat menggunakan Collectors.groupingBydan menggunakan compareTometode untuk mengelompokkan daftar karyawan berdasarkan tanggal sebelumnya, saat ini dan masa depan

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

Jadi hasilnya akan

key--> -1 ---> will have employees with previous date
key--> 0 ---> will have employees with current date
key--> 1 ---> will have employees with future date
Kolam kematian
sumber