【问题标题】:How to cast objects with different classes in a Java 8 stream?如何在 Java 8 流中转换具有不同类的对象?
【发布时间】:2015-03-11 13:54:57
【问题描述】:

用例

我正在使用第 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

问题

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

【问题讨论】:

  • Component3Choice 定义了一个方法getSection() 吗?
  • 你能修改OptionalComponent3BeanRequiredComponent3Bean来实现一个定义getSection()的接口(例如HasSection)吗?
  • 不幸的是,我无权访问该库的源代码。 :(

标签: java java-8 java-stream


【解决方案1】:

不,没有什么能让你免于糟糕的设计,而这似乎是你正在与之抗争的。

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

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

【讨论】:

  • 看起来不错,因为这隔离了逻辑。如果库得到更新并希望得到修复,过渡会更容易。
  • 在另一种情况下响起。想要将 Set 的成员流式传输到 .joining() 但它会查找 CharSequence 实例,例如 String,而不是 Longs 等。这就是我所做的:setOfLongObjects.stream().map(it -> ""+it)。收集(Collectors.joining(“,”))
【解决方案2】:

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

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

这将返回一个Optional<Stream<Something>>

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

【讨论】:

    猜你喜欢
    • 2016-05-02
    • 1970-01-01
    • 2017-01-28
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-11-21
    • 2021-07-25
    相关资源
    最近更新 更多