mon*_*omo 5 java lambda java-8
我一直在探索使用java 8将对象从一种类转换为另一种类.我所拥有的是一堆xjc生成的jaxb类.这些类没有足够友好的结构,因为它们映射xml更多的结构而不是业务对象结构.我不愿意编辑生成的类,因为我喜欢在架构更改时重新生成它们,而不必担心保留自定义.
我有一个类似的架构:
<xs:element name="farm">
<xs:sequence>
<xs:element ref="animal" minOccurs="0" maxOccurs="unbounded"/>
</xs:sequence>
</xs:element>
<xs:element name="animal">
<xs:complexType>
<xs:sequence>
<xs:element ref="goat"/>
<xs:element ref="sheep"/>
</xs:sequence>
<xs:complexType>
</xs:element>
<xs:element name="goat">
<xs:complexType>
<xs:sequence>
goat fields
</xs:sequence>
<xs:complexType>
</xs:element>
<xs:element name="sheep">
<xs:complexType>
<xs:sequence>
sheep fields
</xs:sequence>
<xs:complexType>
</xs:element>
Run Code Online (Sandbox Code Playgroud)
这会生成类似Java的东西:
class Farm
public List<Animal> getAnimals()
class Animal
public Goat getGoat()
public String getGoatField()
public Sheep getSheep()
public String getSheepField()
Run Code Online (Sandbox Code Playgroud)
getGoat
并且getSheep
可以返回null,但它们不能都为null.同样,它们中至少有一个必须为空.这是通过业务规则和数据库约束来强制执行的,但不是在xml中强制执行的(尽管如果有人建议将xml结构化为更像所需的VO,我会全力以赴)
我想把这个班变成
class FarmWrapper
public ArrayList<AnimalVO> getAnimals()
//optional features tbd
//possibly public ArrayList<GoatVO> getGoats()
//possibly public ArrayList<SheepVO> getSheep()
class GoatVO extends AnimalVO
class SheepVO extends AnimalVO
Run Code Online (Sandbox Code Playgroud)
我的想法是做这样的事情:
herd.stream()
.filter(Objects::nonNull)
.map(a -> {
Optional<AnimalVO> goatVO = Optional.ofNullable(a.getGoat())
.map(g -> new GoatVO(g.getGoatField()));
Optional<AnimalVO> sheepVO = Optional.ofNullable(a.getSheep())
.map(s -> new SheepVO(s.getSheepField()));
return goatVO.orElse(sheepVO.get());
})
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
现在我一直在喂它一个清单,一旦它遇到一只无效的羊,它会抛出一个NoSuchElementException
.
我想我有几个问题:
goatVO.orElse(sheepVO.get())
只要goatVO包含null然后NoSuchElementException
在sheepVO包含null时抛出,我在工作中缺少什么我真正在做的是使用生成的jaxb代码并尝试获取生成的类并使其更友好.传统上,项目使用了一个包装类,它通过大量的空检查和int到BigInteger的操作将生成的类转换为VO.
编辑生成的类(山羊,绵羊,动物)是一个非首发,因为我希望保留再生能力而不用担心
我认为你可以通过一些调整来使你的代码正常工作:
List<AnimalVO> list = herd.stream()
.filter(Objects::nonNull)
.map(a -> Optional.ofNullable(a.getGoat())
.map(Goat::getGoatField)
.<AnimalVO>map(GoatVO::new)
.orElseGet(() -> new SheepVO(a.getSheep().getSheepField())))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
注意:与 lambda 相比,我更喜欢方法引用,因此我已转而使用它们。
请注意 中对编译器的提示<AnimalVO>map(GoatVO::new)
。这对于让编译器知道您映射到的类型始终是 an 是必要的AnimalVO
,否则它会推断第一个Optional
返回 aGoatVO
并在第二个Optional
返回 a SheepVO
(并且SheepVO
不是 的后代GoatVO
)中给出编译错误。
另请注意,我使用的是orElseGet()
method 而不是orElse()
. orElseGet()
接收Supplier
默认值的 a,而不是默认值本身。Optional
这意味着仅当第一个值不存在时才会延迟选择默认值。
编辑:如果你的农场里有更多的动物,即除了Goat
和Sheep
,现在你有一个Cow
,这就是你可以做到的:
List<AnimalVO> list = herd.stream()
.filter(Objects::nonNull)
.map(a -> Optional.ofNullable(a.getGoat())
.map(Goat::getGoatField)
.<AnimalVO>map(GoatVO::new)
.orElseGet(() -> Optional.ofNullable(a.getSheep())
.map(Sheep::getSheepField)
.<AnimalVO>map(SheepVO::new)
.orElseGet(() -> new CowVO(a.getCow().getCowField()))))
.collect(Collectors.toList());
Run Code Online (Sandbox Code Playgroud)
归档时间: |
|
查看次数: |
421 次 |
最近记录: |