通过特定逻辑合并整数的ArrayList

时间:2018-12-04 12:41:09

标签: java oop arraylist merge

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

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

我要在列表字段中插入整数值,始终为 1 0 。 由于有许多 User 类对象,它们中的一些是重复项,因为它们具有相同的电子邮件地址,但具有不同的列表

我需要将 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));

我很难实现将许多 list 合并为一个的逻辑。 逻辑并不复杂:只要有 1 ,就将 1 放入合并列表。拥有许多具有 0 的列表和仅有一个 1 的列表,最终合并列表中的值就是 1

我应该采取什么方法来实现此逻辑以合并列表?

3 个答案:

答案 0 :(得分:2)

从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) -> { ...see this answer,它对合并功能进行了一些解释。

您可能想使用toMap收集器来研究my other posts,以熟悉它和ofcourse the API doc

答案 1 :(得分:1)

您可以这样做:

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

答案 2 :(得分:1)

List的值始终为0或1,我建议使用long或long []而不是ArrayList

describe('Component', () => {

  let component: Component;

  beforeEach((() => {

    TestBed.configureTestingModule({
      declarations: [Component]
    })
      .compileComponents();
  }));

  beforeEach(() => {
    const fixture = TestBed.createComponent(Component);
    component = fixture.componentInstance;
  });

  it('should have a defined component', () => {
    expect(component).toBeDefined();
  });

  afterAll(() => {
    TestBed.resetTestingModule();
  });

});

如果标志数量大于32,则使用long []保存更多标志;