【问题标题】:What's the ideal way of combining two Object Arrays in Java在Java中组合两个对象数组的理想方式是什么
【发布时间】:2021-05-14 12:26:05
【问题描述】:

A类:

public class A{
   private String Id;
   private List<Product> products = new ArrayList<>();
}

public class Product{
   private String prodId;
   private String color;
   private String size;
}

例子:

A = { "Id": 1 , products: [{"prodId":"Prod1", "color":"Red", "size":"L"},
    {"prodId":"Prod2", "color":"Green", "size":"L"}] }  

B类:

public class B{
   private String Id;
   private List<ProductAvail> productAvail = new ArrayList<>();
}

public class ProductAvail{
   private String prodId;
   private String availability;
   private String region;
}

例子:

B =  { "Id": 1 , productAvail: [{"prodId":"Prod1", "availability":"Y", "region":"AA"},
     {"prodId":"Prod2", "availability":"N", "region":"BB"}] }

我想把它们合二为一

public class C{
   private String Id;
   private List<Catalog> catalog = new ArrayList<>();
}

public class Catalog{
   private String prodId;
   private String color;
   private String size;
   private String availability;
   private String region;
}

C =  { "Id": 1 , catalog: [{"prodId":"Prod1", "color":"Red", "size":"L", "availability":"Y", "region":"AA"},
 {"prodId":"Prod2", "color":"Green", "size":"L", "availability":"N", "region":"BB"}] }

在不使用两个 for 循环的情况下,在 Java 中执行此操作的理想方法是什么?

【问题讨论】:

  • @HovercraftFullOfEels 我已经解析了,想合二为一,请看上例

标签: java arrays spring


【解决方案1】:

给定:

String aJson = "{ \"id\": 1 ,\"products\": [{\"prodId\":\"Prod1\", \"color\":\"Red\", \"size\":\"L\"}, {\"prodId\":\"Prod2\", \"color\":\"Green\", \"size\":\"L\"}] }";
String bJson = "{ \"id\": 1 ,\"productAvail\": [{\"prodId\":\"Prod1\", \"availability\":\"Y\", \"region\":\"AA\"}, {\"prodId\":\"Prod2\", \"availability\":\"N\", \"region\":\"BB\"}] }";

你可以这样做:

ObjectMapper objectMapper = new ObjectMapper();

A a = objectMapper.readValue(aJson, A.class);
B b = objectMapper.readValue(bJson, B.class);

Map<String, ProductAvail> idToProductAvail = b.getProductAvail().stream()
        .collect(Collectors.toMap(ProductAvail::getProdId, Function.identity()));

List<Catalog> catalogs = a.getProducts().stream()
        .map(p -> {
            ProductAvail pa = idToProductAvail.get(p.getProdId());
            return new Catalog(pa.getProdId(), p.getColor(), p.getSize(),
    pa.getAvailability(), pa.getRegion());
        }).collect(Collectors.toList());

C c = new C(a.getId(), catalogs);

System.out.println(objectMapper.writeValueAsString(c));

输出:

{"id":"1","catalog":[{"prodId":"Prod1","color":"Red","size":"L","availability":"Y","region":"AA"},{"prodId":"Prod2","color":"Green","size":"L","availability":"N","region":"BB"}]}

【讨论】:

  • 在这个问题中包含 JSON 对我来说似乎是偶然的;作者要求在 java 中的两个对象列表上快速运行,而不是在读取时与 Jackson 交错源数据。
  • @RG-Rawlings 由于作者提供了 JSON,我认为最好涵盖这两种情况并提供完整的详细解决方案。我没有看到我在哪里 - “在读取时交错源数据”。我解析了对象。
  • 问题标题和作者的评论说他们想使用 A 和 B,而不是之前的数据。您的解决方案是真实的,但他们的问题有家庭作业的味道。 :p
  • @RG-Rawlings 在这种情况下,您可以跳过这部分,从“地图<..>
【解决方案2】:

假设您想在 Java 中执行此操作,解析您的源数据后,您有两个选择。

  1. 保证您的源数据按 prodId 对两个列表进行排序,并且每个产品都有对应的 ProductAvail。然后,您可以简单地假设第一个索引在第二个索引的相同索引处具有有效条目,并使用单个循环遍历它们。

  2. 更改您的源数据和类成员,以便使用 Maps 而不是 Lists 作为输出,使用 prodId 作为每个条目的键。然后,您可以从 Products 映射中迭代键,并使用它们在单个循环中访问 Product 和 ProductAvail 映射。

-

如果您不能做出 (1) 中的保证或 (2) 中的更改,那么您将陷入foreach product { foreach productavail { ... } } 的最坏情况,因为您必须发现 每个产品的正确 ProductAvail。

您可以采取措施通过将发现的内部列表成员清空并跳过空值来减轻影响,或者通过使用 parallelStream 将每次外部迭代的内部循环抛出到不同的线程,但此时没有任何操作可以避免在 @ 上需要一些重复987654322@ - 最好的情况。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-12-28
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多