当前位置: 首页 > 面试题库 >

Java-合并给定条件的列表对象

仲孙绍元
2023-03-14
问题内容

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

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

并假设我们的List 中包含以下数据

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

在此预期的结果它因为名字,姓氏和类型列表中出现了两次只是合并是常见的结果,而不会错过任何领域的
预期成果

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

问题答案:

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

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

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

分组

这些可以用来对您的用户进行分组

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

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

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

也可以直接将其作为下游收集器提供给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()它们;而且,您不再需要按键,因此

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

地图

就像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());

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



 类似资料:
  • 问题内容: 我有一个带有20个属性的Java类及其相应的getter和setters。我也有两个对象列表:和。 现在,我想合并两个列表,并避免基于和的重复对象。 使用Java 8: 但是我必须在哪里指定属性?我应该重写和方法吗? 问题答案: 如果要实现and ,则 在 类 内部 进行操作。在该类中添加类似的方法 如果您这样做了,在上调用将自动执行正确的操作。 如果您不想(或无法)更改类,则没有平等

  • 我需要从给定的超级列表中提取子列表,如下所述。 假设我有一个“Person”对象的超级列表如下: 让Person类定义如下: 通过使用Java Streams API,我如何获取包含如下条目的子列表(注意,必须获取具有相同名称的对象的重复实例): 有人能帮我用Java 8流API实现这一点吗? 附注:我不会预先知道这些对象的名称是什么值。

  • 我有两个可观测值,一个返回1个元素,另一个返回多个元素。我的目标是在不阻塞的情况下将它们合并在一起,以构建如下对象: 我试过压缩、合并和合并,但似乎都不是解决方案。

  • 我认为这个问题可以用动态规划来解决,但我不能提出递归关系。

  • 我们在Java中有任何聚合器函数来执行下面的聚合吗?