我完全相信我的问题很简单,但我无法用流来做(如果有没有流的方法也会有帮助)假设我们有这个用户列表
public class Users {
String firstName;
String lastName;
double accountBalance;
String type;
String extraField;
}
Run Code Online (Sandbox Code Playgroud)
并假设我们的 List < Users > 中有以下数据
"Users": [{
"firstName": "Scott",
"lastName": "Salisbury",
"accountBalance": "100",
"type" : "A"
}, {
"firstName": "John",
"lastName": "Richards",
"accountBalance": "200",
"type" :"C"
}, {
"firstName": "John",
"lastName": "Richards",
"accountBalance": "200",
"type " : "C",
"ExtraField": "Apply"
}]
Run Code Online (Sandbox Code Playgroud)
这里的预期结果是因为 firstName、lastName 和 type 在列表中出现两次,只需合并常见的结果,而不会丢失任何字段
预期输出
"Users": [{
"firstName": "Scott",
"lastName": "Salisbury",
"accountBalance": "100",
"type" : "A"
}, {
"firstName": "John",
"lastName": "Richards",
"accountBalance": "400",//merged values
"type " : "C",
"ExtraField": "Apply" //value that remains in one object of the list
}]
Run Code Online (Sandbox Code Playgroud)
您可以创建一个包含三个字段的键类,例如
@Data
class UserKey {
String firstName;
String lastName;
String type;
static UserKey from(User user) { /* TODO (trivial) */ }
}
Run Code Online (Sandbox Code Playgroud)
分组依据
这些可用于对您的用户进行分组
Map<UserKey,List<User>> grouped =
users.stream().collect(Collectors.groupingBy(UserKey::from));
Run Code Online (Sandbox Code Playgroud)
然后可以通过以下方式合并这些列表中的每一个
Optional<User> summed = userList.stream()
.collect(Collectors.reducing((u1, u2) -> {
u1.setAccountBalance(u1.accountBalance() + u2.accountBalance());
});
Run Code Online (Sandbox Code Playgroud)
这也可以作为下游收集器直接提供给groupingBy:
Map<UserKey,Optional<User>> mergedMap =
users.stream().collect(Collectors.groupingBy(UserKey::from,
Collectors.reducing((u1, u2) -> {
u1.setAccountBalance(u1.accountBalance() + u2.accountBalance());
return u1;
}));
Run Code Online (Sandbox Code Playgroud)
由于这些Optionals 保证被填充,你可以调用get()它们;另外,你不再需要钥匙了,所以
List<User> result = mergedMap.values().stream()
.map(Optional::get)
.collect(toList());
Run Code Online (Sandbox Code Playgroud)
地图
正如 Naman 在评论中建议的那样,您也可以通过toMap.
Map<UserKey,User> mergedMap = users.stream()
.collect(toMap(UserKey::from, Function.identity(),
(u1, u2) -> {
u1.setAccountBalance(u1.accountBalance() + u2.accountBalance());
return u1;
}));
List<User> result = new ArrayList<>(mergedMap.values());
Run Code Online (Sandbox Code Playgroud)
请注意,reduce 函数具有操作列表中原始用户对象之一的副作用,因此请确保不再需要它们。
| 归档时间: |
|
| 查看次数: |
831 次 |
| 最近记录: |