我有两个不同的相同对象列表,但属性不同,并且在这些对象中有一个公共标识符。我想迭代第一个列表并从第二个列表中获取相应的对象(具有公共属性),然后将这些对象包装起来,最后使用Java Streams将该对象添加到列表中。
这是我采取的例子。
private class Person {
private String name;
private boolean isSenior;
private Person(String name, boolean isSenior) {
this.name = name;
this.isSenior = isSenior;
}
public String getName() {
return name;
}
public boolean isSenior() {
return isSenior;
}
@Override
public String toString() {
return name + ": " + isSenior;
}
}
private class PersonWrapper {
private Person jrPerson;
private Person srPerson;
private PersonWrapper(Person jrPerson, Person srPerson) {
this.jrPerson = jrPerson;
this.srPerson = srPerson;
}
public Person getJrPerson() {
return jrPerson;
}
public Person getSrPerson() {
return srPerson;
}
@Override
public String toString() {
return jrPerson.toString() + "-" + srPerson.toString();
}
}
现在,在主类中,我将创建两个列表实例,如此
List<Person> jrPersons = new ArrayList<>();
List<Person> srPersons = new ArrayList<>();
并按以下方式添加对象
jrList.add(new Person("John", false));
jrList.add(new Person("Paul", false));
jrList.add(new Person("Mike", false));
seniorList.add(new Person("John", true));
seniorList.add(new Person("Paul", true));
seniorList.add(new Person("Mike", true));
现在,我想迭代jrList并在srList(同名)中找到相应的Person对象。然后我将这些对象包装为PersonWrapper
并将该对象包装到列表中。
到目前为止,这就是我一直在做的事情
List<PersonWrapper> wrapperList = new ArrayList<>();
jrList.forEach(jr -> seniorList.stream().filter(sr -> jr.getName().equals(sr.getName())).map(sr -> new PersonWrapper(jr, sr)).collect(Collectors.toList()));
现在,我想知道如何将Collectors.toList()
替换为wrapperList
,或将Collectors.toList()
的输出添加到wrapperList
。
请帮助我实现这一目标。
答案 0 :(得分:12)
而不是使用forEach
而只是从头开始使用流:
List<PersonWrapper> wrapperList = jrList.stream()
.flatMap(jr -> seniorList.stream()
.filter(sr -> jr.getName().equals(sr.getName()))
.map(sr -> new PersonWrapper(jr, sr))
)
.collect(Collectors.toList());
通过使用flatMap
,您可以将}流(<{1}})压缩为单个流(Stream<Stream<PersonWrapper>>
)
如果你不能自己实例化Stream<PersonWrapper>
或者真的需要附加它。您可以将以上代码段更改为以下内容:
wrapperList
答案 1 :(得分:3)
虽然Lino's回答肯定是正确的。我认为,如果jrList
中的某个人物对象只能在seniorList
最多只有一个相应的匹配,换句话说,如果它是1-1关系,那么你可以改进Lino通过查找第一个匹配项给出的解决方案如下:
List<PersonWrapper> resultSet = jrList.stream()
.map(p -> seniorList.stream()
.filter(sr -> p.getName().equals(sr.getName()))
.findFirst()
.map(q -> new PersonWrapper(p, q))
.get())
.collect(Collectors.toList());
或如果无法保证jrList
中的每个人都会在seniorList
中找到相应的匹配项,那么请将上述查询更改为:
List<PersonWrapper> resultSet = jrList.stream()
.map(p -> seniorList.stream()
.filter(sr -> p.getName().equals(sr.getName()))
.findFirst()
.map(q -> new PersonWrapper(p, q))
.orElse(null))
.filter(Objects::nonNull)
.collect(Collectors.toList());
不同之处在于,现在我们不会在get()
的结果上调用findFirst()
,而是在orElse
无法找到相应值的情况下提供findFirst
的默认值,然后我们filter
null
值在随后的中间操作中输出,因为它们不需要。
答案 2 :(得分:-1)
用下面的代码替换你的循环逻辑。
jrList.forEach(jr -> seniorList.stream().filter(sr -> jr.getName().equals(sr.getName()))
.map(sr -> wrapperList.add(new PersonWrapper(jr, sr))).collect(Collectors.toList()));