如何使用流使用嵌套对象有效地读取 soap Web 服务响应

how effciently read soap web service response with nested objects using streams

我认为一项非常简单的任务是使用 Java 8 个流来解析由 soap 网络服务响应的嵌套对象。尽管如此,当我考虑正确或最合适的使用方法时,我还是很困惑。我知道这要视情况而定,永远不会有简单的食谱。在过去的两周里,我一直在阅读在哪里以及如何使用流,但我无法就几个选项得出最终结论。如果我在处理 soap 客户端时基于非常常见的需求正确理解了实际​​应用程序,如果有人可以提供技术意见,我会提出以下四种方法。

我不想要像 "Here I do successfully this way so you can copy and paste similar idea" 这样简单的答案。我真的很想知道我是否正确应用了到目前为止所读的内容。

首先,网络服务回答了我的嵌套对象:

//一级

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "OndernemingAlgemeenType", propOrder = {
    "adressen",
    ... others properties
})
@XmlSeeAlso({
    Onderneming20Type.class
})
public class OndernemingAlgemeenType
{

    @XmlElement(name = "Adressen")
    protected AdresOndernemingLijstType adressen;
    ... others elements
}   

//return列表的第二层

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

    @XmlElement(name = "Adres", required = true)
    protected List<AdresOndernemingType> adres; 
    ...
}

// 第三级用于过滤列表 return 只有一个 AdresOndernemingType

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AdresOndernemingType", propOrder = {
    "type"
})
public class AdresOndernemingType
    extends AdresOndernemingBasisType{
    @XmlElement(name = "Type", required = true)
    protected TypeAdresOndernemingType type;
}

//第四层

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AdresOndernemingBasisType", propOrder = {
   ... not relevant for this question
})
@XmlSeeAlso({
    AdresOndernemingType.class
})
public class AdresOndernemingBasisType
    extends AdresBasisType
{
       ... not relevant for this question
}

//第五层,最后,需要的字段(街道和城市)

@XmlAccessorType(XmlAccessType.FIELD)
@XmlType(name = "AdresBasisType", propOrder = {
    "straat", //street
    "gemeente" //city
})
@XmlSeeAlso({
    AdresOndernemingDeelnemingInType.class,
    AdresOndernemingBasisType.class
})
public class AdresBasisType {

    @XmlElement(name = "Straat")
    protected StraatRR20Type straat;
    @XmlElement(name = "Gemeente")
    protected GemeenteOptioneel20Type gemeente;

// 与其理解接近

方法一: 我知道这是空异常安全的。 我的意思是,如果 getAdressen 或 getAdres 为空,则完全没有例外,也不会打印地址。

private void printOptionalDidactic(){
        Optional<AdresOndernemingLijstType> op = Optional.ofNullable(onderneming.getAdressen());
        op.map(AdresOndernemingLijstType::getAdres).get().stream().filter(Objects::nonNull)
        .filter(o -> "001".equals(o.getType().getCode().getValue().getValue()))
        .map(x -> System.out.println("My street is: ".concat(x.getStraat())));
}       

方法二: 假设永远不会有 null 元素(minOccurs="1" in xsd for all)所以使用 Optional 将毫无意义

private void printNoOptionalDidactic(){     
        onderneming.getAdressen().getAdres().stream()
        .filter(o -> "001".equals(o.getType().getCode().getValue().getValue()))
        .map(x -> System.out.println("My street is: ".concat(x.getStraat())));
}

方法三: 假设我想打印所有街道并且我不关心过滤,我知道在 forEach 之前使用 flatMap 没有任何优势

private void printForEachDidactic(){
        onderneming.getAdressen().getAdres().stream()
        .forEach(x -> System.out.println("My street is: ".concat(x.getStraat())));
}       

方法四 由于过程中使用的谓词和函数没有使用共享资源, 我知道我可以使用并行性。尽管如此,只要数据很少,所以我没有真正的收获 Should I always use a parallel stream when possible?

private void printParallelDidactic(){
        onderneming.getAdressen().getAdres().parallelStream()
        .filter(o -> "001".equals(o.getType().getCode().getValue().getValue()))
        .map(x -> System.out.println("My street is: ".concat(x.getStraat())));
}

当您确实不映射流的元素时(例如,在方法 1 .map(x -> System.out.println... 中),我不会使用 map 流方法。最好叫forEach,它专门为流的每个元素执行代码。

关于您的第一种方法,我认为如果 onderneming.getAdressen() 为空,则会抛出 NoSuchElementException。查看 Optional.get:

的实现
public T get() {
    if (value == null) {
        throw new NoSuchElementException("No value present");
    }
    return value;
}

否则,从代码的角度来看,所有方法看起来都是有效的。当然我不能说你的数据模型。

但是,您不需要应用 Java 8 流和 lambda 只是因为 Java 8 引入了它们。例如,我不会在您的方法 3 中使用流。老派的 for 循环也会这样做(并且在这里 IMO 的可读性更高):

for (AdresOndernemingType x : onderneming.getAdressen().getAdres()) {
    System.out.println("My street is: ".concat(x.getStraat())));
}

关于并行流,我不会使用 parallel() 除非我真的需要并行性来获得大型数据集或长 运行 任务的性能。