我正在尝试使用 Java8 流过滤和收集具有条件的对象
我有一个实例列表,它有一个嵌套的元素列表
public class Model {
List<Instance> instances;
}
public class Instance {
private String name;
List<Element> elements;
}
public class Element {
private String partNumber;
}
下面是例子josn
{
"instances": [
{
"name": "instance1",
"elements": [
{
"partNumber": "partNumber1"
},
{
"partNumber": "partNumber2"
}
]
},
{
"name": "instance2",
"elements": [
{
"partNumber": "partNumber3"
},
{
"partNumber": "partNumber4"
}
]
}
]
}
和其他响应对象
public class Response {
private List<Domain> domains;
}
public class Domain {
private String name;
private List<Hardware> hardwares;
}
public class Hardware {
private String partNumber;
}
样本 json
{
"domains": [
{
"name": "domain1",
"hardwares": [
{
"partNumber": "partNumber1"
}
]
},
{
"name": "domain2",
"hardwares": [
{
"partNumber": "partNumber2"
},
{
"partNumber": "partNumber3"
},
{
"partNumber": "partNumber4"
}
]
},
{
"name": "domain3",
"hardwares": [
{
"partNumber": "partNumber5"
},
{
"partNumber": "partNumber6"
}
]
}
]
}
我正在尝试通过比较来自域的 Hardwares
是否至少包含来自请求的每个元素的 partnumber
来流式传输和收集响应对象。这意味着每个 Instance
中至少有一个 hardware
应该出现在 Domains
hardware
中,以考虑 Domain
作为有效代码。
对于上面的示例数据,
- domain1 不是有效域,因为它至少包含
一个
partnumber
partNumber1
来自instance1
但不包含 至少一个partnumber
来自instance2
- domain2 是有效的
域,因为它至少包含一个
partnumber
partNumber2
来自instance1
并包含至少一个partnumber
partNumber3
来自instance2
。它可以包含其他零件号,即 好的 - domain3 不是有效域,因为它不包含
至少一个来自
instance1
的partnumber
并且不包含 至少一个来自instance2
的
partnumber
我开始写了
request.getInstances().stream().flatMap(instance -> instance.getElement().stream().filter(element -> response.getDomains().stream().flatMap(domain -> domain.getHardwares.stream().anyMatch(hardware-> element.contains()
但是由于我对流的理解有限,所以我很难完成这个
最佳答案
您可能可以在一个流中完成所有操作,但我建议使用两个流。首先,从模型中生成一组零件名称列表;然后,通过响应流式传输以查找域,这样对于每个实例,该实例的部件名称集中包含来自该域的某个部件名称。
List<Set<String>> parts = model.getInstances().stream()
.map(i -> i.getElements().stream()
.map(Element::getPartNumber)
.collect(Collectors.toSet()))
.collect(Collectors.toList());
response.getDomains().stream()
.filter(d -> parts.stream()
.allMatch(p -> d.getHardwares().stream()
.map(Hardware::getPartNumber)
.anyMatch(p::contains)))
.forEach(System.out::println);
关于您的评论:现在,如果有一个没有元素的实例,这应该会删除所有域,因为 allMatch
将对该实例失败。相反,如果没有元素的实例应该被忽略,您可以将另一个 filter
添加到第一个流以创建 parts
列表(未测试):
.filter(i -> ! i.getElements().isEmpty())
或者可能是 i.getElements() != null
,具体取决于它的初始化方式。
关于java - 通过使用条件嵌套的列表元素将其与另一个列表匹配来过滤对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56688050/