让我们想象下面的对象:
class People {
public int id;
public String name;
public Date dateOfDeath;
}
我有2个人名单。
在第一个中,People对象正确设置了ID和NAME。在第二个中,People对象的ID和DATEOFDEATH正确设置。
我需要合并2个列表,以便拥有一个包含完整People对象的名单(姓名和死亡日期)。
以完整的程序方式,这可以通过双循环来完成,如下所示:
for (People fullPeople : firstList) {
for (People peopleWithDateOfDeath : secondList) {
if (peopleWithDateOfDeath.id == fullPeople.id) {
fullPeople.dateOfDeath = peopleWithDateOfDeath.dateOfDeath;
break;
}
}
}
secondList = null;
// first list is good :)
如何以功能方式实现此功能?我使用的是Rx-Java,但Java 8 Streams的任何示例都可以轻松转换。
答案 0 :(得分:4)
您可以通过构建id
到dateOfDeath
的地图来避免O(n 2 )的复杂性:
Map<Integer, Date> deaths = secondList.stream()
.collect(toMap(p -> p.id, p -> p.dateOfDeath));
fullPeople.stream()
.filter(p -> deaths.containsKey(p.id))
.forEach(p -> p.dateOfDeath = deaths.get(p.id));
或者,如果你想避免改变现有的人:
List<People> mergedPeople = fullPeople.stream()
.map(p -> deaths.containsKey(p.id)
? new People(p.id, p.name, deaths.get(p.id))
: p
).collect(toList());
答案 1 :(得分:2)
你可以这样做:
List<People> persons =
names.stream()
.map(p -> new People(p.id, p.name, dates.stream()
.filter(pd -> pd.id == p.id)
.map(pd -> pd.dateOfDeath)
.findFirst()
.orElse(null))
)
.collect(Collectors.toList());
其中names
是具有姓名的人员名单,dates
是具有死亡日期的人员名单。这假设People
类有一个3参数构造函数来获取id,name和死亡日期。
对于拥有姓名的所有人,使用filter
在另一个列表中查找具有相同ID的人,并将结果映射到dateOfDeath
。如果找到匹配项,则返回日期,否则,将调用orElse
并返回null
。
请注意,这不会合并dates
列表中但不在names
列表中的任何人。
示例代码:
List<People> names = new ArrayList<>();
List<People> dates = new ArrayList<>();
names.add(new People(1, "Name 1", null));
names.add(new People(2, "Name 2", null));
dates.add(new People(1, null, new Date()));
dates.add(new People(3, null, new Date()));
List<People> peoples = codeFromAbove();
System.out.println(peoples);
// prints
// [[id=1, name=Name 1, date=Sun Oct 18 19:48:58 CEST 2015],
// [id=2, name=Name 2, date=null]]
使用:
class People {
public int id;
public String name;
public Date dateOfDeath;
public People(int id, String name, Date dateOfDeath) {
this.id = id;
this.name = name;
this.dateOfDeath = dateOfDeath;
}
@Override
public String toString() {
return "[id="+id+", name="+name+", date="+dateOfDeath+"]";
}
}