Java-合并给定条件的列表对象 [英] Java - Merge objects of list given a condition

查看:70
本文介绍了Java-合并给定条件的列表对象的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我坚信我的问题很简单,但是我无法使用流进行处理(如果有一种方法可以不使用流进行处理,那么它也会有所帮助) 假设我们有此用户列表

I uttlerly convinced that my question its quite simple but im unable to do it with streams (if there is a way to do it without stream will be helpfull too) Suppose that we have this list of users

public class Users {
   String firstName;
   String lastName;
   double accountBalance;
   String type;
   String extraField;
}

,并假设我们的列表中有以下数据<用户>

and suppose that we have the following data in my 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"
        }]

给定firstName,lastName和type在列表中出现两次的预期结果,只需合并常见结果而不遗漏任何字段
预期产量

the expected result here its given that firstName, lastName and type appears twice on the list just merge the results that are common without missing any field
Expected output

"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
        }]  

推荐答案

您可以创建一个包含三个字段的键类,例如

You can create a key class containing the three fields, like

@Data
class UserKey {
    String firstName;
    String lastName;
    String type;

    static UserKey from(User user) { /* TODO (trivial) */ }
}

分组

可以用来对用户进行分组

Those can be used to group your users

Map<UserKey,List<User>> grouped = 
    users.stream().collect(Collectors.groupingBy(UserKey::from));

然后,这些列表中的每一个都可以通过合并

Each of these lists can then be merged by

Optional<User> summed = userList.stream()
    .collect(Collectors.reducing((u1, u2) -> {
        u1.setAccountBalance(u1.accountBalance() + u2.accountBalance());
    });

这也可以直接作为groupingBy的下游收集器提供:

This can also be given directly as a downstream collector to the 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;
        }));

由于保证可以填充这些Optional,因此您可以在其上调用get();而且,您不再需要按键,所以

Since those Optionals are guaranteed to be filled, you can just call get() on them; also, you don't need the keys anymore, so

List<User> result = mergedMap.values().stream()
                 .map(Optional::get)
                 .collect(toList());

toMap

正如Naman在评论中所建议的那样,您也可以通过toMap对此进行快捷操作.

As Naman suggested in the comments, you can also shortcut this by 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());

请注意,reduce函数具有操作列表中原始用户对象之一的副作用,因此请确保您不再需要它们.

Note that the reducing function has the side effect of manipulating one of the original user objects in the list, so make sure you don't need them again.

这篇关于Java-合并给定条件的列表对象的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆