如何使用可选和过滤来从wsdl2java生成的链接/级联对象中检索对象

时间:2017-11-10 18:01:31

标签: lambda java-8 stream wsdl optional

我理解在处理Java中的分层对象时建议使用flatMap,特别是在从XML文件创建的对象中提取值时。

不依赖于Optional,因为getCommercieleNaam()会给我一个列表,我编码:

NaamOndernemingLijstCommercieelType naamOndernemingLijstCommercieel = onderneming.getNamen()
        .getCommercieleNamen();
NaamOndernemingType naamOndernemingType = naamOndernemingLijstCommercieel.getCommercieleNaam().stream()
        .filter(x -> x.getTaalcode().getValue() == "nl").findFirst().get();

简而言之,它会抛出级联对象并返回为荷兰语发现的名字。我认为这是非常不安全的,而不是检查所有对象是否为null,我更喜欢使用Optional。

然后我尝试代码,我理解它是正确的方法,但我不知道如何应用过滤器,以便只从列表中检索符合条件的对象(在我的场景中语言==“nl”):

    Optional<NamenOndernemingType> optionalNamenOnderneming = onderneming.getNamen(); 
    NaamOndernemingType naamOndernemingType = optionalNamenOnderneming.flatMap(NamenOndernemingType::getCommercieleNamen)
            .flatMap(NaamOndernemingLijstCommercieelType::getCommercieleNaam)
            .filter(x -> "nl".equals(x.toString()));

PS。:在荷兰语中,naam表示名称(单数),Namen表示名称(复数)

嗯,我得到的最接近的是

    Optional<NamenOndernemingType> optionalNamenOnderneming = Optional.ofNullable(onderneming.getNamen());
    List<NaamOndernemingType> listNaamOndernemingType = optionalNamenOnderneming
            .flatMap(NamenOndernemingType::getCommercieleNamen)
            .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam);

但它既不起作用,在我解决之后,我也需要过滤。

*编辑

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "NamenOndernemingType", propOrder = {
    "maatschappelijkeNamen",
    "afgekorteNamen",
    "commercieleNamen"
})
public class NamenOndernemingType {

...

    public NaamOndernemingLijstCommercieelType getCommercieleNamen() {
        return commercieleNamen;
    }


@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "NaamOndernemingLijstCommercieelType", propOrder = {
    "commercieleNaam"
})
public class NaamOndernemingLijstCommercieelType {
...

    public List<NaamOndernemingType> getCommercieleNaam() {

enter image description here

*解决方案*

Optional.ofNullable(onderneming.getNamen()).map(NamenOndernemingType::getCommercieleNamen)
                .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam).get().stream().filter(Objects::nonNull)
                .filter(x -> x.getTaalcode().getValue() == "nl").findFirst()
                .ifPresent(o -> myMethod("onderneming_commerciele_naam", o.getNaam().getValue()));

PS:未来的读者我的发现值得一读我的另一个问题: how use Optional with cascaded objects not created with Optional

2 个答案:

答案 0 :(得分:1)

我认为您不需要地图,因为您已经说getCommercieleNaam返回List<NaamOndernemingType>因此,一旦我们宣称我们将拥有一个Stream<NaamOndernemingType>,我们可以找到所有以"nl"作为字符串表示的对象。

List<NaamOndernemingType> listNaamOndernemingType = optionalNamenOnderneming
           .flatMap(NaamOndernemingLijstCommercieelType::getCommercieleNaam)              
           .filter(Objects::nonNull)
           .filter(x -> "nl".equals(x.toString()))
           .orElse(null);

鉴于Optional没有collect作为终端操作,我们可以简单地使用orElse返回值(如果存在),否则返回null。在这种情况下,List<NaamOndernemingType>

注意 - 如果您想将Stream<Stream<R>>更改为Stream<T>,则只需要调用 flatMap ,否则您只需要调用地图将返回Stream<R>

答案 1 :(得分:0)

感谢Aominè的建议以及基于how use Optional with cascaded objects not created with Optional

的讨论

我达到了这个解决方案:

Optional.ofNullable(onderneming.getNamen()).map(NamenOndernemingType::getCommercieleNamen)
                .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam).get().stream().filter(Objects::nonNull)
                .filter(x -> x.getTaalcode().getValue() == "nl").findFirst()
                .ifPresent(o -> myMethod("onderneming_commerciele_naam", o.getNaam().getValue()));