简体   繁体   English

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

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

Use Case 用例

I'm using an 3rd party library where there are two very similar classes that don't implement an interface. 我正在使用第3方库,其中有两个非常相似的类没有实现接口。 The code currently loops through a list of items to find the first occurrence of an object using one of these classes and then converts it to a stream where it is processed. 该代码当前循环浏览项目列表,以使用这些类之一查找对象的首次出现,然后将其转换为在其中进行处理的流。 It would be nice if I could convert this code to use a stream and have it chained to the rest of my code. 如果可以将这段代码转换为使用流并将其链接到其余代码,那将是很好的。

Current Code 当前代码

    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 ...

Desired Code 所需代码

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

Question

Is it possible cast the entry based on the previous filter in the stream? 是否可以根据流中的前一个过滤器强制转换条目?

No, nothing can save you from bad design, which is what it seems you're fighting against. 不,没有什么可以使您免受不良设计的困扰,这似乎是您要与之对抗的东西。

You can force a common interface by means of a wrapper, if you need to replicate boilerplate similar to this one in many places. 如果需要在许多地方复制与此样板相似的样板,则可以通过包装器强制使用公共接口。 Otherwise, I guess the best you can do is 否则,我想你能做的最好的就是

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

Not the prettiest code, but you could do : 不是最漂亮的代码,但是您可以:

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

This would return an Optional<Stream<Something>> . 这将返回Optional<Stream<Something>>

Note that findFirst must be the last operation, since it's terminal. 请注意,因为findFirst是终端,所以它必须是最后一个操作。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM