首页 > 解决方案 > 将几个不同对象的集合合并为一个

问题描述

我从外部 API 收到了几个对象集合。对于这个例子,假设它们看起来像这样。在实际场景中,我无法修改这些类。

@Data
public class ExternalResourceA {
    private LocalDate date;
    private String type;
}

@Data
public class ExternalResourceB {
    private LocalDate date;
    private String id;
}

而且我有自己的课程,它结合了这两个基于一些在这里不重要的业务规则。另外,和上面一样,这是生成的类,不能编辑它。我所能做的就是编写包装类,然后将其转换为原始类。

@Data
public class MyResource {
    private LocalDate date;
    private String type;
    private String id;
}

对于这个例子,假设这是我从 API 获取的数据

 private List<ExternalResourceA> externalCollectionA() {
     final List<ExternalResourceA> collection = new ArrayList<>();
     final var today = LocalDate.now();
     for(int i = 0 ; i < 36; i++) {
         collection.add(new ExternalResourceA(today.minusMonths(i), "type" + i));
     }
     Collections.shuffle(collection);
     return collection;
 }

 private List<ExternalResourceB> externalCollectionB() {
     final List<ExternalResourceB> collection = new ArrayList<>();
     final var today = LocalDate.now();
     for(int i = 0 ; i < 36; i++) {
         collection.add(new ExternalResourceB(today.minusMonths(i), "id" + i));
     }
     Collections.shuffle(collection);
     return collection;
 }

现在,我需要合并 2019 年和 2019 年的数据ExternalResourceA并将ExternalResourceB其保存到MyResource. 有些数据可能会丢失,例如我得到了 2019 年 3 月的 A,但我没有 2019 年 3 月的 B。

我设法做到了这样

void filterResources() {
    final var resourceAin2019 = getAFrom2019(externalCollectionA());
    final var resourceBin2019 = getBFrom2019(externalCollectionB());
    final List<MyResource> myCollection = new ArrayList<>();
    for(int i = 0; i <= 12; i++) {
        final var resource = new MyResource();
        findA(resourceAin2019, i).ifPresent(res -> {
            resource.setDate(res.getDate());
            resource.setType(res.getType());
        });
        findB(resourceBin2019, i).ifPresent(res -> {
            resource.setId(res.getId());
        });
        myCollection.add(resource);
    }
    myCollection.forEach(System.out::println);
}

private Optional<ExternalResourceA> findA(List<ExternalResourceA> list, int index) {
    return list.size() > index ? Optional.ofNullable(list.get(index)) : Optional.empty();
}

private Optional<ExternalResourceB> findB(List<ExternalResourceB> list, int index) {
    return list.size() > index ? Optional.ofNullable(list.get(index)) : Optional.empty();
}

private List<ExternalResourceA> getAFrom2019(List<ExternalResourceA> resource) {
    return resource.stream()
            .filter(res -> res.getDate().isAfter(LocalDate.parse("2019-01-01") || res.getDate().isEqual(LocalDate.parse("2019-01-01")))
            .sorted(Comparator.comparing(ExternalResourceA::getDate))
            .collect(Collectors.toList());
}

private List<ExternalResourceB> getBFrom2019(List<ExternalResourceB> resource) {
    return resource.stream()
            .filter(res -> res.getDate().isAfter(LocalDate.parse("2019-01-01") || res.getDate().isEqual(LocalDate.parse("2019-01-01")))
            .sorted(Comparator.comparing(ExternalResourceB::getDate))
            .collect(Collectors.toList());
}

它有点工作,但即使在这个简单的例子中,也有很多几乎相同的函数,它们只是在其他类上运行。在实际场景中,这会增长得更多,因为我需要处理更多的结构。我想知道是否有可能使这个更清洁和更简单?

编辑#经过进一步检查,我的解决方案没有按预期工作,显示比解释更简单,这是我丢失ExternalResourceB2019 年 3 月的数据时的结果,最后一个元素出现了空值。

在此处输入图像描述

标签: javacollectionsjava-stream

解决方案


推荐阅读