List of Employees with Java streamから、特定の日付の前後の従業員を取得します。


9

参加日が異なるs がListありEmployeeます。ストリームを使用してリストから参加する特定の日付の前後に従業員を取得したい。

私は次のコードを試しました、

 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は、述部に従って入力要素を分割し、それらをMap<Boolean, List<T>>

これはの従業員を処理しないことに注意してくださいspecificDate


1
コードの説明は素晴らしいでしょう。
Vishwa Ratna

2
これは正確には行われません。問題のコードは何をしますか-の従業員specificDatefalseパーティションに着陸し、問題のコードのどこにもありません
Andronicus

追加specificDate.plusDays(1)するとどのように問題が解決しますか?一部のspecificDateままになりますfalse
Andronicus

その後、trueパーティションに配置されます...
アンドロニカス

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ああ、はい、私はそれを逃しました、ありがとう!
アンドロニカス

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.