Java 스트림을 사용하여 직원 목록에서 특정 날짜 전후에 직원을 확보하십시오.


9

내가 가진 ListEmployee다른 가입 기간에의. 스트림을 사용하여 목록에서 특정 날짜를 시작하기 전후에 직원을 확보하고 싶습니다.

나는 다음 코드를 시도했다.

 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파티션에 있을 것입니다 .
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.