web-dev-qa-db-fra.com

Vérifier instance de flux

J'ai l'expression suivante:

scheduleIntervalContainers.stream()
        .filter(sic -> ((ScheduleIntervalContainer) sic).getStartTime() != ((ScheduleIntervalContainer)sic).getEndTime())
        .collect(Collectors.toList());

... où scheduleIntervalContainers a le type d'élément ScheduleContainer:

final List<ScheduleContainer> scheduleIntervalContainers

Est-il possible de vérifier le type avant le filtre?

58
quma

Vous pouvez appliquer un autre filter afin de ne conserver que les occurrences de ScheduleIntervalContainer, et l'ajout d'un map vous fera économiser les distributions suivantes:

scheduleIntervalContainers.stream()
    .filter(sc -> sc instanceof ScheduleIntervalContainer)
    .map (sc -> (ScheduleIntervalContainer) sc)
    .filter(sic -> sic.getStartTime() != sic.getEndTime())
    .collect(Collectors.toList());

Comme le commentait Holger, vous pouvez remplacer les expressions lambda par des références de méthodes si vous préférez ce style:

scheduleIntervalContainers.stream()
    .filter(ScheduleIntervalContainer.class::isInstance)
    .map (ScheduleIntervalContainer.class::cast)
    .filter(sic -> sic.getStartTime() != sic.getEndTime())
    .collect(Collectors.toList());
80
Eran

Une option assez élégante consiste à utiliser la méthode reference de la classe:

scheduleIntervalContainers
  .stream()
  .filter( ScheduleIntervalContainer.class::isInstance )
  .map( ScheduleIntervalContainer.class::cast )
  .filter( sic -> sic.getStartTime() != sic.getEndTime())
  .collect(Collectors.toList() );
103
Ricardo Gasca

Il y a un petit problème avec @ Eran solution - taper le nom de la classe à la fois filter et map est sujet aux erreurs - il est facile d'oublier de changer le nom de la classe dans les deux endroits. Une solution améliorée ressemblerait à ceci:

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

Cependant, la création de Stream pour chaque élément correspondant peut être pénalisée. Veillez à l'utiliser sur des ensembles de données énormes. J'ai appris cette solution de @ Tagir Vailev

12
Andrey