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

Java-在给定条件下合并列表的对象,java,java-stream,Java,Java Stream,我完全相信我的问题很简单,但我不能用流来做(如果有一种方法可以不用流来做也会很有帮助) 假设我们有这个用户列表 public class Users { String firstName; String lastName; double accountBalance; String type; String extraField; } 假设我的列表中有以下数据 "Users": [{ "firstName": "Scott",

我完全相信我的问题很简单,但我不能用流来做(如果有一种方法可以不用流来做也会很有帮助) 假设我们有这个用户列表

public class Users {
   String firstName;
   String lastName;
   double accountBalance;
   String type;
   String extraField;
}
假设我的列表中有以下数据

"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在列表中出现两次,只需合并常见的结果而不丢失任何字段
预期产量

"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));
由于那些
可选的
s保证被填充,所以您可以对它们调用
get()
;而且,你不再需要钥匙了,所以

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

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

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

@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));
由于那些
可选的
s保证被填充,所以您可以对它们调用
get()
;而且,你不再需要钥匙了,所以

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

请注意,缩减功能的副作用是操作列表中的一个原始用户对象,因此请确保不再需要它们。

如果数据只是对象列表,那么您应该能够通过几个循环相当直接地合并数据。例如:

public static ArrayList<User> mergeData(ArrayList<User> userList) {
  ArrayList<User> users = new ArrayList<>(userList);

  for(int i = 0; i < users.size(); i++) {
      User currentUser = users.get(i);
      for(int j = i + 1; j < users.size(); j++) {
          User otherUser = users.get(j);

          if(currentUser.firstName.equals(otherUser.firstName) 
            && currentUser.lastName.equals(otherUser.lastName)
            && currentUser.type.equals(otherUser.type)) {
                //Apply the field merging
                currentUser.accountBalance += otherUser.accountBalance;
                if(currentUser.extraField == null) {
                    currentUser.extraField = otherUser.extraField;
                } else {
                    //Handle case where you pick whether to keep the value or not.
                }

                //Remove the merged data and move index back to account for removal
                users.remove(j);
                j--;
           }
      }
  }

  return users;
}
公共静态ArrayList合并数据(ArrayList用户列表){
ArrayList users=新的ArrayList(userList);
对于(int i=0;i

代码只是遍历这些值,将其与列表中的其他所有剩余值进行比较,在适用的情况下进行合并,然后从列表的其余部分删除合并对象,然后再转到下一个值。

如果数据只是对象列表,然后,您应该能够通过几个循环相当直接地合并数据。例如:

public static ArrayList<User> mergeData(ArrayList<User> userList) {
  ArrayList<User> users = new ArrayList<>(userList);

  for(int i = 0; i < users.size(); i++) {
      User currentUser = users.get(i);
      for(int j = i + 1; j < users.size(); j++) {
          User otherUser = users.get(j);

          if(currentUser.firstName.equals(otherUser.firstName) 
            && currentUser.lastName.equals(otherUser.lastName)
            && currentUser.type.equals(otherUser.type)) {
                //Apply the field merging
                currentUser.accountBalance += otherUser.accountBalance;
                if(currentUser.extraField == null) {
                    currentUser.extraField = otherUser.extraField;
                } else {
                    //Handle case where you pick whether to keep the value or not.
                }

                //Remove the merged data and move index back to account for removal
                users.remove(j);
                j--;
           }
      }
  }

  return users;
}
公共静态ArrayList合并数据(ArrayList用户列表){
ArrayList users=新的ArrayList(userList);
对于(int i=0;i

代码只是遍历这些值,将其与列表中的其他所有剩余值进行比较,在适用的情况下进行合并,然后从列表的其余部分删除合并对象,然后再转到下一个值。

bean中可能有多少字段?@GovindaSakhare这是一个示例,使用此supose 5字段,您是否使用任何库来处理此数据?例如,您可以首先使用
groupingBy
和提取关键字段的函数对它们进行分组;这将按键提供用户列表。然后,您可以通过提供下游收集器来合并这些字段。@daniu当然可以,让我们来看看。bean中可以有多少字段?@GovindaSakhare这是一个示例,有了这个supose 5字段,您是否使用任何库来处理这些数据?例如,您可以首先使用
groupingBy
和提取关键字段的函数对它们进行分组;这将按键提供用户列表。然后,您可以通过提供一个下游收集器来合并这些对象。@daniu当然可以,让我们这样做。这不是收集器。toMap()吗??我发现无法解决方法“identity”错误,你不应该使用方法引用。您应该使用Function.identity()。如果您使用方法引用,您基本上是在试图通过供应商。@Ramana更正,谢谢。我为
收集器
方法使用并暗示静态导入。这不是Collectors.toMap()吗??我发现无法解决方法“identity”错误,你不应该使用方法引用。您应该使用Function.identity()。如果您使用方法引用,您基本上是在试图通过供应商。@Ramana更正,谢谢。我为
收集器
方法使用并暗示静态导入。