【问题标题】:Merge ArrayList of Integers by specific logic按特定逻辑合并 ArrayList of Integers
【发布时间】:2019-05-05 21:33:18
【问题描述】:

我的 ArrayList 包含我的简单模型类 User 的许多实例,其中仅包含 2 个字段:

@Data
public class User {
    private String email;
    private ArrayList<Integer> lists; 
}    

我在 lists 字段中插入整数值,总是 10User 类有许多对象,其中一些是重复的,因为它们具有相同的 email 地址但不同的列表

我需要将 Users 的重复项合并到 User 的一个对象中,同时还要注意 lists 字段。

User user1 = new User('email@gmail.com', Arrays.asList(0, 1, 0, 1, 1)); 
User user2 = new User('email@gmail.com', Arrays.asList(0, 0, 0, 1, 1));
User user3 = new User('email@gmail.com', Arrays.asList(1, 1, 1, 1, 1));
/* merge duplicated objects into one */
User mergedUser = new User('email@gmail.com', Arrays.asList(1, 1, 1, 1, 1));

我在实现将许多 列表 合并为一个的逻辑时遇到了困难。 其背后的逻辑并不复杂:只要有1,就将1放入合并列表。有许多具有 0 且只有一个 1 的列表,会在最终合并列表中产生值 1

我应该采取什么方法来实现这个合并列表的逻辑?

【问题讨论】:

    标签: java oop arraylist merge


    【解决方案1】:

    从JDK8开始,你可以使用toMap方法来完成你的任务。

    Collection<User> result = 
            list.stream()
               .collect(toMap(User::getEmail,
                       Function.identity(),
                       (l, r) -> {
                           List<Integer> firstList = l.getList();
                           List<Integer> secondList = r.getList();
                         IntStream.range(0, firstList.size())
                                  .forEach(i -> firstList.set(i, Math.max(firstList.get(i), secondList.get(i))));
                                return l;
                       })).values();
    

    您可以通过将合并逻辑提取到辅助方法中来进一步使其更具可读性:

    private static User apply(User l, User r) {
            List<Integer> firstList = l.getList();
            List<Integer> secondList = r.getList();
            IntStream.range(0, firstList.size())
                    .forEach(i -> firstList.set(i, Math.max(firstList.get(i), secondList.get(i))));
            return l;
    }
    

    那么你可以这样做:

    Collection<User> result = list.stream()
                    .collect(toMap(User::getEmail, Function.identity(), Main::apply))
                    .values();
    

    其中Main 指的是包含apply 方法的类。


    注意这里重要的是合并函数 ((l, r) -&gt; { ...),see this answer 稍微解释了合并函数。

    您可能需要使用toMap 收集器来了解my other posts 以熟悉它和ofcourse the API doc

    【讨论】:

      【解决方案2】:

      你可以这样做:

      List<User> finalList = new ArrayList<>(users.stream()
              .collect(Collectors.toMap(User::getEmail, Function.identity(), (user1, user2) -> {
                  List<Integer> l1 = user1.getLists();
                  List<Integer> l2 = user2.getLists();
                  List<Integer> merge = IntStream.range(0, l1.size())
                          .mapToObj(i -> (l1.get(i) == 0 && l2.get(i) == 0) ? 0 : 1)
                          .collect(Collectors.toList());
                  return new User(user1.getEmail(), merge);
              })).values());
      

      【讨论】:

        【解决方案3】:

        List的值总是0或者1,我推荐使用long或者long[]而不是ArrayList

        @Data
        @AllArgsConstructor
        public class User {
          private String email;
          private long flags;
        
          public static long merge(long... flags) {
            long result = 0;
            for (long flag : flags) {
              result = result | flag;
            }
            return result;
          }
        
        
          // test
          public static void main(String[] args) {
            User user1 = new User("email@gmail.com", Long.valueOf("1000000000000101",2));
            User user2 = new User("email@gmail.com", Long.valueOf("0000111100000101",2));
            User user3 = new User("email@gmail.com", Long.valueOf("0000000010110101",2));
            System.out.println(Long.toBinaryString(merge(user1.flags, user2.flags, user3.flags)));
            // result is 1000111110110101
          }
        }
        

        如果flags的数量大于32,使用long[]保存更多的flags;

        【讨论】:

        • 我无法理解这会给mergedUser 提供什么,如 OP 所示?
        • 用户 mergeUser = new User("email@gmail.com", merge(user1.flags, user2.flags, user3.flags));
        猜你喜欢
        • 2023-04-05
        • 2023-04-01
        • 2018-10-15
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2017-02-23
        • 2015-12-18
        相关资源
        最近更新 更多