Filtered Stream with any match on two objects set a value of one object to the value of another object

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

Filtered Stream with any match on two objects set a value of one object to the value of another object

问题

长时间的读者/潜水者第一次发帖
可能是一个有点愚蠢的问题我相信有一个简单的解决办法

我有一个客户列表和一个供应商列表

客户
```java
    private int ID;
    private String name;
    private Integer age;
    private LocalDateTime createdDate;
    private String supplerName;

供应商:

    private int ID;
    private String name;
    private Integer age;
    private int customerID;
    private LocalDateTime createdDate;

我正在获取一些虚拟信息:

List<Supplier> suppliersList = supplierRepository.findAll();
List<Customer> customersList = customerRepository.findAll();

这将返回类似于以下内容:

供应商列表:
==============================================================================================
  Supplier{ID=1, name='Supplier A', age=19, customerID=1, createdDate=2020-09-25T23:15:31.798}
, Supplier{ID=2, name='Supplier B', age=20, customerID=1, createdDate=2020-09-25T23:15:31.799}
, Supplier{ID=3, name='Supplier C', age=21, customerID=2, createdDate=2020-09-25T23:15:31.799}
, Supplier{ID=4, name='Supplier D', age=22, customerID=3, createdDate=2020-09-25T23:15:31.799}
==============================================================================================
客户列表:
  Customer{ID=1, name='Customer A', age=19, createdDate=2020-09-25T23:15:31.770}
, Customer{ID=2, name='Customer B', age=20, createdDate=2020-09-25T23:15:31.779}
, Customer{ID=3, name='Customer C', age=21, createdDate=2020-09-25T23:15:31.779}
, Customer{ID=4, name='Customer D', age=22, createdDate=2020-09-25T23:15:31.779}
==============================================================================================

基本上,我想要做的是,如果供应商中的customerID与客户中的ID匹配,我希望将客户的supplierName设置为供应商中的name值。

我已经有一个流,它找到了匹配项:

List<Customer> filteredList = customersList.stream()
                .filter(cust -> suppliersList.stream()
                        .anyMatch(supl -> String.valueOf(cust.getID())
                                .equals(String.valueOf(supl.getCustomerID())))
                ).collect(Collectors.toList());

这会为我找到3个匹配的ID生成以下输出:

  Customer{ID=1, name='Customer A', age=19, createdDate=2020-09-25T23:22:16.768}
, Customer{ID=2, name='Customer B', age=20, createdDate=2020-09-25T23:22:16.776}
, Customer{ID=3, name='Customer C', age=21, createdDate=2020-09-25T23:22:16.777}

长话短说,我想要实现的是,对于所有这些匹配项,我想要将客户的供应商名称设置为供应商中的name值。

在某个时候,我还想将另一个对象流加入(这样我们现在会有3个流),并将一个对象中的一个或多个值设置到另一个对象中。如果有人有解决办法的话,那就更好了 Filtered Stream with any match on two objects set a value of one object to the value of another object


<details>
<summary>英文:</summary>

Long time reader/ lurker in the shadows, first time poster.
Might be a bit of a silly question and I am sure there is an easy solution.

What I have is a List of Customers and a List of Suppliers

Customers:
```java
    private int ID;
    private String name;
    private Integer age;
    private LocalDateTime createdDate;
    private String supplerName;

Suppliers

    private int ID;
    private String name;
    private Integer age;
    private int customerID;
    private LocalDateTime createdDate;

I am fetching some dummy info with:

List&lt;Supplier&gt; suppliersList = supplierRepository.findAll();
List&lt;Customer&gt; customersList = customerRepository.findAll();

Which is returning me something like this:

Suppliers List:
==============================================================================================
  Supplier{ID=1, name=&#39;Supplier A&#39;, age=19, customerID=1, createdDate=2020-09-25T23:15:31.798}
, Supplier{ID=2, name=&#39;Supplier B&#39;, age=20, customerID=1, createdDate=2020-09-25T23:15:31.799}
, Supplier{ID=3, name=&#39;Supplier C&#39;, age=21, customerID=2, createdDate=2020-09-25T23:15:31.799}
, Supplier{ID=4, name=&#39;Supplier D&#39;, age=22, customerID=3, createdDate=2020-09-25T23:15:31.799}
==============================================================================================
Customers List:
  Customer{ID=1, name=&#39;Customer A&#39;, age=19, createdDate=2020-09-25T23:15:31.770}
, Customer{ID=2, name=&#39;Customer B&#39;, age=20, createdDate=2020-09-25T23:15:31.779}
, Customer{ID=3, name=&#39;Customer C&#39;, age=21, createdDate=2020-09-25T23:15:31.779}
, Customer{ID=4, name=&#39;Customer D&#39;, age=22, createdDate=2020-09-25T23:15:31.779}
==============================================================================================

Basically what I want to do is if the customerID in Suppliers matches the ID in customer I want to set the supplierName in customers to the name value from Suppliers.

I already have a stream that is finding me the matches

List&lt;Customer&gt; filteredList = customersList.stream()
                .filter(cust -&gt; suppliersList.stream()
                        .anyMatch(supl -&gt; String.valueOf(cust.getID())
                                .equals(String.valueOf(supl.getCustomerID())))
                ).collect(Collectors.toList());

which gives me the following output for the 3 matched ID's

  Customer{ID=1, name=&#39;Customer A&#39;, age=19, createdDate=2020-09-25T23:22:16.768}
, Customer{ID=2, name=&#39;Customer B&#39;, age=20, createdDate=2020-09-25T23:22:16.776}
, Customer{ID=3, name=&#39;Customer C&#39;, age=21, createdDate=2020-09-25T23:22:16.777}

So long story short what I am trying to achieve is for all these matches I want to set the Customer supplierName to the name value in Supplier.

At some point I would also like to also join another stream of objects (so we would now have 3 streams) and set one or multiple values from one object to another. Bonus points if anyone has a solution for that Filtered Stream with any match on two objects set a value of one object to the value of another object

答案1

得分: 1

我认为这个任务最好不要使用纯流解决方案来完成。以下是分步骤的做法:

Map<Integer, List<Supplier>> suppliersByCustomerId = suppliersList.stream()
        .collect(Collectors.groupingBy(Supplier::getCustomerID));

这将供应商按customerID分组。然后,我们需要迭代客户,并检查是否有供应商为每个客户提供服务。如果有匹配项,我们将第一个供应商的名称设置给客户。

customers.forEach(c -> {
    List<Supplier> suppliers = suppliersByCustomerId.get(c.getID());
    if (suppliers != null && !suppliers.isEmpty()) {
        Supplier first = suppliers.get(0);
        String supplierName = first.getName();
        c.setSupplierName(supplierName);
    }
});

由于您没有指定如果每个客户有多个供应商要执行什么操作,所以我决定将第一个供应商的名称设置给客户。

英文:

I think this task is better done without a pure stream solution. Here it is, separated in steps:

Map&lt;Integer, List&lt;Supplier&gt;&gt; suppliersByCustomerId = suppliersList.stream()
        .collect(Collectors.groupingBy(Supplier::getCustomerID));

This groups suppliers by customerID. Then, we need to iterate the customers and check if there are suppliers for each one of them. If there's a match, we set the name of the first supplier to the customer.

customers.forEach(c -&gt; {
    List&lt;Supplier&gt; suppliers = suppliersByCustomerId.get(c.getID());
    if (suppliers != null &amp;&amp; !suppliers.isEmpty()) {
        Supplier first = suppliers.get(0);
        String suppliername = first.getName();
        c.setSupplierName(supplierName);
    }
});

As you are not specifying what to do if there are many suppliers per customer, I've decided to set the name of the first supplier to the customer.

huangapple
  • 本文由 发表于 2020年9月25日 21:28:21
  • 转载请务必保留本文链接:https://go.coder-hub.com/64065101.html
匿名

发表评论

匿名网友

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

确定