如何使用流使用嵌套对象有效地读取 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()
除非我真的需要并行性来获得大型数据集或长 运行 任务的性能。
我认为一项非常简单的任务是使用 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()
除非我真的需要并行性来获得大型数据集或长 运行 任务的性能。