合并自定义对象列表到一个单一的列表对象使用 Java 8 的流。

huangapple go评论76阅读模式
英文:

Merge List of Custom Objects to a Single List Object using Streams Java 8

问题

我有一个ProductInfo对象,看起来像这样

ProductInfo.java

public class ProductInfo
{
private List<String> servicetagInfo;
}

我有一个类似这样的Order对象,其中包含Products信息的列表

OrderDetail.java

public class OrderDetail
{
private String orderNum;
private List<ProductInfo> productInfo;
}

然后我有一个Response对象,基本上包含Order对象的列表

Response.java

public class Response
{
private List<OrderDetail> orderInfo;
}

我得到了预期的响应。但是现在是这种格式

orderInfo:
0: {orderNum: "162293591",...}
 productInfo:
 0: {servicetag_info: ["7LSMW33", "49SMW33"]}
 1: {servicetag_info: ["JF6XN33", "CQ5XN33"]}
 2: {servicetag_info: ["5VRR523", "13LR523"]}

在这里,我试图将productInfo列表合并为这样

productInfo:
0: {servicetag_info: ["7LSMW33", "49SMW33","JF6XN33", "CQ5XN33","5VRR523", "13LR523"]}

只需将所有字符串添加到一个主属性中。

这是我的代码

List<String> serviceTagList = new ArrayList<>();
for (OrderDetail orderDetail : arInvoiceOrderResponseBody.getOrders()) {  //Here i am getting orders from external service
    if (orderDetail != null) {
        if (orderDetail.getProductInfo() != null && orderDetail.getProductInfo().size() > 0) {
            for (ProductInfo productInfoDetail : orderDetail.getProductInfo()) {
                if (productInfoDetail != null) {
                    if (productInfoDetail.getServicetagInfo() != null) {
                        for (String serviceTag : productInfoDetail.getServicetagInfo()) {
                            serviceTagList.add(serviceTag);
                        }
                    }
                }
            }
        }
    }
    ProductInfo productInfo = new ProductInfo();
    productInfo.setServicetagInfo(serviceTagList);
    orderDetail.setProductInfo(Arrays.asList(productInfo));
}

有人能建议我如何在Java中使用流来实现相同的效果,以便更易读。

英文:

I have ProductInfo object which looks like this

ProductInfo.java

    public class ProductInfo
    {
    private List<String> servicetagInfo;
    }

I have Order object like this which has list of Products info

OrderDetail.java

    public class OrderDetail
    {
    private String orderNum;
    private List<ProductInfo> productInfo;
    }

And then I have a Response object which basically has List of Order objects

Response.java

    public class Response
    {
    private List<OrderDetail> orderInfo;
    }  

I am getting response as expected.But right now in this format

    orderInfo:
    0: {orderNum: "162293591",...}
     productInfo:
     0: {servicetag_info: ["7LSMW33", "49SMW33"]}
     1: {servicetag_info: ["JF6XN33", "CQ5XN33"]}
     2: {servicetag_info: ["5VRR523", "13LR523"]}

Here I am trying to merge productInfo List to be like this

    productInfo:
    0: {servicetag_info: ["7LSMW33", "49SMW33","JF6XN33", "CQ5XN33","5VRR523", "13LR523"]}

Just add all strings into one main property.

Here is my code

    List<String> serviceTagList = new ArrayList<>();
    for (OrderDetail orderDetail : arInvoiceOrderResponseBody.getOrders()) {  //Here i am getting orders from external service
		if (orderDetail != null) {
			if (orderDetail.getProductInfo() != null && orderDetail.getProductInfo().size() > 0) {
				for (ProductInfo productInfoDetail : orderDetail.getProductInfo()) {
					if (productInfoDetail != null) {
						if (productInfoDetail.getServicetagInfo() != null) {
							for (String serviceTag : productInfoDetail.getServicetagInfo()) {
								serviceTagList.add(serviceTag);
							}
                       }
					}
                }
			}
		}
		ProductInfo productInfo = new ProductInfo();
		productInfo.setServicetagInfo(serviceTagList);
		orderDetail.setProductInfo(Arrays.asList(productInfo));
	}         

Can anyone suggest how can i achieve same using streams in java so that it will be readable.

答案1

得分: 2

尝试这个:

Set<String> tags = order.stream()
        .flatMap(order -> order.getProductInfo().stream())
        .map(ProductInfo::getServicetagInfo)
        .collect(Collectors.toSet());

完整实现:

for (OrderDetail orderDetail : arInvoiceOrderResponseBody.getOrders()) {
    if (orderDetail != null && orderDetail.getProductInfo() != null) {
        orderDetail.getProductInfo().removeAll(null); // 移除任何空元素
        Set<String> tags = orderDetail.getProductInfo().stream()
                .flatMap(product -> (product.getServicetagInfo() == null) ? null : product.getServicetagInfo().stream())
                .collect(Collectors.toSet());
        tags.remove(null); // 移除空值(如果存在)

        ProductInfo productInfo = new ProductInfo();
        productInfo.setServicetagInfo(tags);
        orderDetail.setProductInfo(Arrays.asList(productInfo));
    }
}
英文:

Try this:

Set&lt;String&gt; tags = order.stream()
			.flatMap(order -&gt; order.getProductInfo().stream())
			.map(ProductInfo::getServicetagInfo)
			.collect(Collectors.toSet());

Full implementation:

for (OrderDetail orderDetail : arInvoiceOrderResponseBody.getOrders()) {
    if (orderDetail != null &amp;&amp; orderDetail.getProductInfo() != null) {
        orderDetail.getProductInfo().removeAll(null); // Remove any null elems
        Set&lt;String&gt; tags = orderDetail.getProductInfo().stream()
			.flatMap(product -&gt; (product.getServicetagInfo() == null) ? null : product.getServicetagInfo().stream())
			.collect(Collectors.toSet());
        tags.remove(null); // Remove null if exists
    }

    ProductInfo productInfo = new ProductInfo();
    productInfo.setServicetagInfo(tags);
    orderDetail.setProductInfo(Arrays.asList(productInfo));
}

答案2

得分: 2

使用流(Streams)后,你的代码可以像这样:

arInvoiceOrderResponseBody.getOrders().stream()
        .filter(Objects::nonNull)
        .forEach(YourClassName::mergeProductInfo);

mergeProductInfo 方法如下:

private static void mergeProductInfo(OrderDetail orderDetail) {

    List<String> serviceTagList = new ArrayList<>();

    if (orderDetail.getProductInfo() != null) {
        serviceTagList = orderDetail.getProductInfo().stream()
                .filter(Objects::nonNull)
                .map(ProductInfo::getServicetagInfo)
                .filter(Objects::nonNull)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }

    ProductInfo productInfo = new ProductInfo();
    productInfo.setServicetagInfo(serviceTagList);
    orderDetail.setProductInfo(Arrays.asList(productInfo));
}

如果你可以确保不会收到空列表或元素,代码可以更简化。

英文:

With streams your code could be like this:

arInvoiceOrderResponseBody.getOrders().stream()
            .filter(Objects::nonNull)
            .forEach(YourClassName::mergeProductInfo);

The method mergeProductInfo would be:

private static void mergeProductInfo(OrderDetail orderDetail) {

    List&lt;String&gt; serviceTagList = new ArrayList&lt;&gt;();

    if (orderDetail.getProductInfo() != null) {
        serviceTagList = orderDetail.getProductInfo().stream()
                .filter(Objects::nonNull)
                .map(ProductInfo::getServicetagInfo)
                .filter(Objects::nonNull)
                .flatMap(Collection::stream)
                .collect(Collectors.toList());
    }

    ProductInfo productInfo = new ProductInfo();
    productInfo.setServicetagInfo(serviceTagList);
    orderDetail.setProductInfo(Arrays.asList(productInfo));
}

It could be simplified if you could be sure that you are not going to receive null lists or elements.

huangapple
  • 本文由 发表于 2020年7月30日 23:25:24
  • 转载请务必保留本文链接:https://go.coder-hub.com/63176421.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定