[java] 스트림에서 instanceof 확인
다음식이 있습니다.
scheduleIntervalContainers.stream()
.filter(sic -> ((ScheduleIntervalContainer) sic).getStartTime() != ((ScheduleIntervalContainer)sic).getEndTime())
.collect(Collectors.toList());
… scheduleIntervalContainers
요소 유형이 있는 위치 ScheduleContainer
:
final List<ScheduleContainer> scheduleIntervalContainers
필터 전에 타입을 확인할 수 있습니까?
답변
인스턴스 filter
만 유지하기 위해 다른 것을 적용 할 수 ScheduleIntervalContainer
있으며를 추가 map
하면 나중에 캐스트를 저장할 수 있습니다.
scheduleIntervalContainers.stream()
.filter(sc -> sc instanceof ScheduleIntervalContainer)
.map (sc -> (ScheduleIntervalContainer) sc)
.filter(sic -> sic.getStartTime() != sic.getEndTime())
.collect(Collectors.toList());
또는 Holger가 언급했듯이 해당 스타일을 선호하는 경우 람다 식을 메서드 참조로 바꿀 수 있습니다.
scheduleIntervalContainers.stream()
.filter(ScheduleIntervalContainer.class::isInstance)
.map (ScheduleIntervalContainer.class::cast)
.filter(sic -> sic.getStartTime() != sic.getEndTime())
.collect(Collectors.toList());
답변
매우 우아한 옵션은 클래스의 메서드 참조를 사용하는 것입니다.
scheduleIntervalContainers
.stream()
.filter( ScheduleIntervalContainer.class::isInstance )
.map( ScheduleIntervalContainer.class::cast )
.filter( sic -> sic.getStartTime() != sic.getEndTime())
.collect(Collectors.toList() );
답변
@ Eran 솔루션 에는 작은 문제가 있습니다 . 둘 다에 클래스 이름을 입력 filter
하고 map
오류가 발생하기 쉽습니다. 두 위치에서 클래스 이름을 변경하는 것을 잊기 쉽습니다. 개선 된 솔루션은 다음과 같습니다.
private static <T, R> Function<T, Stream<R>> select(Class<R> clazz) {
return e -> clazz.isInstance(e) ? Stream.of(clazz.cast(e)) : null;
}
scheduleIntervalContainers
.stream()
.flatMap(select(ScheduleIntervalContainer.class))
.filter( sic -> sic.getStartTime() != sic.getEndTime())
.collect(Collectors.toList());
그러나 Stream
일치하는 모든 요소에 대해 를 생성하면 성능이 저하 될 수 있습니다 . 거대한 데이터 세트에서 사용하도록주의하십시오. @ Tagir Vailev 에서이 솔루션을 배웠습니다.