首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >如何使用可选对象与级联对象一起使用可选对象

如何使用可选对象与级联对象一起使用可选对象
EN

Stack Overflow用户
提问于 2017-11-13 11:01:12
回答 1查看 400关注 0票数 0

上下文:我有由wsdl2java生成的链式对象,所以它们中没有一个包含java.util.Optional。有一个已经创建的方法,它调用soap服务,接收xml并将其解压缩为级联对象。

愿望:为了避免空测试,我想使用可选的。

我已经发布了我的成绩单(how to use optional and filter along to retrieve an object from chained/cascaded objects generated by wsdl2java),但是,经过3天的搜索和阅读,我真的被困住了,我意识到我的知识有一些差距,所以我决定后退一步,在前进之前尝试一个更简单的解决方案。

我想知道我是否真的在尝试一些可能的事情:在没有考虑可选模式的级联对象中使用可选对象。我在互联网上找到的大多数示例要么使用用“私有可选myObj”编码的级联对象,要么限制它们只对对象使用Optional.of,而不是使用wsdl2java生成的对象树。

以下是我到目前为止试图找出是否有可能的地方,我也被困住了:我跟随http://www.oracle.com/technetwork/articles/java/java8-optional-2175753.html,并尝试应用相同的想法,设想对象最初是用Java7编码的(根本就没有私有的可选myObj )。

首先,正如Oracle文章(从父到子依赖关系)所显示的那样:

USB

代码语言:javascript
复制
public class USB {

    String version;
    public USB() {

    }
    public String getVersion() {
        return version;
    }
    public void setVersion(String version) {
        this.version = version;
    }
}

OptionalSoundcard

代码语言:javascript
复制
public class OptionalSoundcard {

    private Optional<USB> usb;

    public OptionalSoundcard() {
        // TODO Auto-generated constructor stub
    }

    public Optional<USB> getUsb() {
        return usb;
    }

    public void setUsb(Optional<USB> usb) {
        this.usb = usb;
    }

}

OptionalComputer

代码语言:javascript
复制
public class OptionalComputer {

    private Optional<OptionalSoundcard> soundcard;  

    public OptionalComputer() {
    }

    public Optional<OptionalSoundcard> getSoundcard() {
        return soundcard;
    }

    public void setSoundcard(Optional<OptionalSoundcard> soundcard) {
        this.soundcard = soundcard;
    }

}

和成功的测试

代码语言:javascript
复制
@Test
public void runOptionalClassicOracleExample() throws Exception {

    USB usb = new USB();
    usb.setVersion("1");

    OptionalSoundcard soundcard = new OptionalSoundcard();
    soundcard.setUsb(Optional.ofNullable(usb));

    OptionalComputer computer = new OptionalComputer();
    computer.setSoundcard(Optional.ofNullable(soundcard));

    Optional<OptionalComputer> sc = Optional.of(computer);
    // Optional<Computer> sc = Optional.ofNullable(computer);
    String v1 = sc.flatMap(OptionalComputer::getSoundcard).flatMap(OptionalSoundcard::getUsb).map(USB::getVersion)
            .orElse("UNKNOWN");

    assertThat(v1, is(equalTo("1")));

}

现在,想象一下使用Java 7模式创建的同一台计算机和Soundcar (USB类与上面的相同)

声卡

代码语言:javascript
复制
public class Soundcard {

    private USB usb;

    public Soundcard() {
        // TODO Auto-generated constructor stub
    }

    public USB getUsb() {
        return usb;
    }

    public void setUsb(USB usb) {
        this.usb = usb;
    }

}

电脑

代码语言:javascript
复制
public class Computer {

    private Soundcard soundcard;  

    public Computer() {
        // TODO Auto-generated constructor stub
    }

    public Soundcard getSoundcard() {
        return soundcard;
    }

    public void setSoundcard(Soundcard soundcard) {
        this.soundcard = soundcard;
    }

}

甚至没有编译的测试

代码语言:javascript
复制
@Test
public void runClassicOracleExample() throws Exception {

    USB usb = new USB();
    usb.setVersion("2");

    Soundcard soundcard = new Soundcard();
    soundcard.setUsb(usb);

    Computer computer = new Computer();
    computer.setSoundcard(soundcard);

    Optional<Computer> sc = Optional.ofNullable(computer);
    String v1 = sc.flatMap(Computer::getSoundcard).flatMap(Soundcard::getUsb).map(USB::getVersion)
            .orElse("UNKNOWN");

    assertThat(v1, is(equalTo("2")));
}

错误是:

类型可选中的方法flatMap(Function>)不适用于参数( Computer ::getSoundcard) --来自计算机类型的getSoundcard()类型是声卡,这与描述符的返回类型:可选不兼容

*编辑

在现实世界里

代码语言:javascript
复制
NamenOndernemingType 1 X 1 NaamOndernemingLijstCommercieelType 1 X List<> NaamOndernemingType

我知道这三者都会产生相同的结果,除了一个细节:零安全。

代码语言:javascript
复制
// no Optional at all and no map() at all
NaamOndernemingLijstCommercieelType naamOndernemingLijstCommercieel = onderneming.getNamen()
        .getCommercieleNamen();
NaamOndernemingType naamOnderneming1 = naamOndernemingLijstCommercieel.getCommercieleNaam().stream()
        .filter(x -> x.getTaalcode().getValue() == "nl").findFirst().get();

// Optional.ofNullable wrapped only the list and flatMap the list
Optional<List<NaamOndernemingType>> optionalList = Optional
        .ofNullable(onderneming.getNamen().getCommercieleNamen().getCommercieleNaam());
NaamOndernemingType naamOnderneming2 = optionalList
        .flatMap(list -> list.stream().filter(s -> "nl".equals(s.getTaalcode().getValue())).findFirst()).get();

// Optional.ofNUllable on root element and map all other "levels" until get the
// list and strem()
Optional<NamenOndernemingType> optionalNamenOnderneming = Optional.ofNullable(onderneming.getNamen());
NaamOndernemingType naamOnderneminge = optionalNamenOnderneming.map(NamenOndernemingType::getCommercieleNamen)
        .map(NaamOndernemingLijstCommercieelType::getCommercieleNaam).get().stream().filter(Objects::nonNull)
        .filter(x -> x.getTaalcode().getValue() == "nl").findFirst().get();

*未来的读者可能认为值得阅读how to use optional and filter along to retrieve an object from chained/cascaded objects generated by wsdl2java

我最后的解决办法是:

代码语言:javascript
复制
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()));
EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2017-11-13 12:12:07

为什么不直接使用.map()

因为根据Optional#flatMap()的java文档

如果存在值,则向其应用提供的Optional-bearing映射函数,返回结果,否则返回一个空的Optional。此方法与Optional,类似,但提供的映射器的结果已经是,如果调用,flatMap不会将其包装为额外的Optional

flatMap中使用的映射程序必须返回一个Optional。我认为map会更好地满足你的需要。因为它将Computer#getSoundcard()的结果封装在一个可选的文件中。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/47262770

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档