如何在 Java 8 流中投射具有不同 类 的对象?

How to cast objects with different classes in a Java 8 stream?

用例

我正在使用第 3 方库,其中有两个非常相似的 类 没有实现接口。该代码当前循环遍历项目列表,以使用其中一个 类 查找对象的第一次出现,然后将其转换为处理它的流。如果我可以将此代码转换为使用流并将其链接到我的其余代码,那就太好了。

当前代码

    for (Component3Choice component: components) {
        if (component instanceof OptionalComponent3Bean) {
            OptionalComponent3Bean section = (OptionalComponent3Bean) component;

            entryStream = section.getSection().getEntry().stream()
            break;
        }
        else if (component instanceof RequiredComponent3Bean) {
            RequiredComponent3Bean section = (RequiredComponent3Bean) component;

            entryStream = section.getSection().getEntry().stream();
            break;
        }
    }
    ... do something with the stream ...

所需代码

components.stream()
  .filter(entry -> entry instanceof OptionalComponent3Bean 
                     || entry instanceof RequiredComponent3Bean)
  .findFirst()
  .map( {{ cast entry }} )
  .map( castedEntry.getSection().getEntry())
  ... continue on with my processing

问题

是否可以根据流中的前一个过滤器投射条目?

不是最漂亮的代码,但你可以做到:

components.stream()
          .filter(entry -> entry instanceof OptionalComponent3Bean 
                     || entry instanceof RequiredComponent3Bean)
          .map(entry -> {
                 if ((entry instanceof OptionalComponent3Bean)
                   return ((OptionalComponent3Bean) entry).getSection().getEntry().stream(); 
                 else
                   return ((RequiredComponent3Bean) entry).getSection().getEntry().stream();
                        })
          .findFirst();

这会 return 一个 Optional<Stream<Something>>

请注意,findFirst 必须是最后一个操作,因为它是终止操作。

不,没有什么可以使您免于糟糕的设计,这似乎是您正在与之抗争的。

如果您需要在许多地方复制与此类似的样板文件,您可以通过包装器强制使用通用接口。 否则,我想你能做的最好的就是

static private IDontKnow getStream(Component3Choice c3c) {
  if (c3c instanceof OptionalComponent3Bean) {
    return ((OptionalComponent3Bean)c3c).getStream();
  } else if (c3c instanceof RequiredComponent3Bean) {
    return ((RequiredComponent3Bean)c3c).getStream();
  } else {
    return null;
  }
}

components.stream()
  .map(x -> getStream(x))
  .filter(x -> x!=null)
  .findFirst()
  .map(x -> x.getEntry().stream());
  ... continue on with yout processing