您可以将两个构造函数和一个 merge 方法添加到将组合联系人的 Account 类:
public class Account {
private final Integer accountId;
private List<String> contacts = new ArrayList<>();
public Account(Integer accountId) {
this.accountId = accountId;
}
// Copy constructor
public Account(Account another) {
this.accountId = another.accountId;
this.contacts = new ArrayList<>(another.contacts);
}
public Account merge(Account another) {
this.contacts.addAll(another.contacts);
return this;
}
// TODO getters and setters
}
那么,您有几个选择。一种是使用Collectors.toMap将账户收集到一个地图上,通过accountId进行分组,并通过Account.merge的方法合并具有相等accountId的账户的联系人。最后,获取地图的值:
Collection<Account> result = accounts.stream()
.collect(Collectors.toMap(
Account::getAccountId, // group by accountId (keys)
Account::new, // use copy constructor (values)
Account::merge)) // merge values with equal key
.values();
您需要对这些值使用复制构造函数,否则在调用Account.merge 时您会改变原始列表的帐户。
一种等效的方法(没有流)是使用Map.merge 方法:
Map<Integer, Account> map = new HashMap<>();
accounts.forEach(a ->
map.merge(a.getAccountId(), new Account(a), Account::merge));
Collection<Account> result = map.values();
同样,您需要使用复制构造函数来避免对原始列表的帐户进行不希望的更改。
更优化的第三种选择(因为它不会为列表的每个元素创建一个新帐户)包括使用Map.computeIfAbsent 方法:
Map<Integer, Account> map = new HashMap<>();
accounts.forEach(a -> map.computeIfAbsent(
a.getAccountId(), // group by accountId (keys)
Account::new) // invoke new Account(accountId) if absent
.merge(a)); // merge account's contacts
Collection<Account> result = map.values();
以上所有选项都返回Collection<Account>。如果你需要List<Account>,你可以这样做:
List<Account> list = new ArrayList<>(result);