上下文:我有由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
public class USB {
String version;
public USB() {
}
public String getVersion() {
return version;
}
public void setVersion(String version) {
this.version = version;
}
}OptionalSoundcard
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
public class OptionalComputer {
private Optional<OptionalSoundcard> soundcard;
public OptionalComputer() {
}
public Optional<OptionalSoundcard> getSoundcard() {
return soundcard;
}
public void setSoundcard(Optional<OptionalSoundcard> soundcard) {
this.soundcard = soundcard;
}
}和成功的测试
@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类与上面的相同)
声卡
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;
}
}电脑
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;
}
}甚至没有编译的测试
@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()类型是声卡,这与描述符的返回类型:可选不兼容
*编辑
在现实世界里
NamenOndernemingType 1 X 1 NaamOndernemingLijstCommercieelType 1 X List<> NaamOndernemingType我知道这三者都会产生相同的结果,除了一个细节:零安全。
// 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
我最后的解决办法是:
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()));发布于 2017-11-13 12:12:07
为什么不直接使用.map()
因为根据Optional#flatMap()的java文档
如果存在值,则向其应用提供的
Optional-bearing映射函数,返回结果,否则返回一个空的Optional。此方法与Optional,类似,但提供的映射器的结果已经是,如果调用,flatMap不会将其包装为额外的Optional。
flatMap中使用的映射程序必须返回一个Optional。我认为map会更好地满足你的需要。因为它将Computer#getSoundcard()的结果封装在一个可选的文件中。
https://stackoverflow.com/questions/47262770
复制相似问题