检查流中的instanceof

问题描述 投票:0回答:5

我有以下表情:

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

...其中

scheduleIntervalContainers
具有元素类型
ScheduleContainer
:

final List<ScheduleContainer> scheduleIntervalContainers

可以检查过滤器前的类型吗?

java java-8 java-stream instanceof
5个回答
202
投票

您可以应用另一个

filter
以便仅保留
ScheduleIntervalContainer
实例,并且添加
map
将为您节省以后的转换:

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

或者,正如 Holger 所评论的,如果您喜欢这种风格,您可以用方法引用替换 lambda 表达式:

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

139
投票

一个非常优雅的选择是使用类的方法引用:

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

15
投票

@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

学到了这个解决方案

1
投票

我会推荐这种实用方法,而不是像其他答案建议的那样使用过滤器+地图:

public static <Super, Sub extends Super> Function<Super, Stream<Sub>> filterType(Class<Sub> clz) {
  return obj -> clz.isInstance(obj) ? Stream.of(clz.cast(obj)) : Stream.empty();
}

将其用作:

Stream.of(dog, cat fish)
  .flatMap(filterType(Dog.class));

与filter+map相比有以下优点:

  • 如果该类没有扩展您的类,您将收到编译错误
  • 单一位置,您永远不会忘记更改过滤器或地图中的类

1
投票

使用 StreamEx

按类类型过滤
StreamEx.of(myCollection).select(TheThing.class).toList();
© www.soinside.com 2019 - 2024. All rights reserved.