【问题标题】:How to use groupingBy on nested lists如何在嵌套列表中使用 groupingBy
【发布时间】:2021-05-03 14:39:19
【问题描述】:

我面临一个棘手的情况,我必须在具有嵌套列表的对象上使用 groupingBy。我用 map()、flatmap()、toMap() 尝试了一些东西,但无法提出解决方案,只能绕圈子。非常感谢流专家的任何帮助。我需要在我的 OrdersAnalyzer 类中实现 2 个方法。 这是我的对象的样子:

public class Order {
  private final String id;
  private final Set<OrderLine> orderLines = new HashSet<>();
  private final Customer customer;

  //getters, setters, equals, hashcode omitted for brevity
}
public class OrderLine {
  private final Product product;
  private final Integer quantity;

  //getters, setters, equals, hashcode omitted for brevity
}
public class Product {
  private final String name;
  private final BigDecimal price;

  //getters, setters, equals, hashcode omitted for brevity
}
public class OrdersAnalyzer {
    /**
     * Should return at most three most popular products. Most popular product is the product that have the most occurrences
     * in given orders (ignoring product quantity).
     * If two products have the same popularity, then products should be ordered by name
     *
     * @param orders orders stream
     * @return list with up to three most popular products
     */
    public List<Product> findThreeMostPopularProducts(Stream<Order> orders) {
      orders.forEach(order -> {
        order.getOrderLines().stream().collect(
          Collectors.groupingBy(OrderLine::getProduct, *What to add here?* )
        );
      });
    }

    /**
     * Should return the most valuable customer, that is the customer that has the highest value of all placed orders.
     * If two customers have the same orders value, then any of them should be returned.
     *
     * @param orders orders stream
     * @return Optional of most valuable customer
     */
    public Optional<Customer> findMostValuableCustomer(Stream<Order> orders) {
      orders.collect(
        Collectors.groupingBy(Order::getCustomer, *What to add here?*)
      );
    }
}

【问题讨论】:

  • 为什么你认为你需要使用Collectors.groupingBy
  • @YassinHajaj 在删除之前,我查看了您的代码 sn-p 工作正常 :) 谢谢 :)

标签: java collections java-8 java-stream groupingby


【解决方案1】:

查找ThreeMostPopularProducts

您希望支持的 API 需要您创建产品频率图,以便在您找到 top-N 时进行查找。在这种情况下,Collectors.counting() 将是一个很好的使用 downstream

请注意,它会为您提供Map&lt;Product, Long&gt; productFrequency 作为结果,然后您需要定义一个自定义Comparator&lt;Map.Entry&lt;Product, Long&gt;&gt; 以辅助对名称比较进行额外检查。

此外,遍历此映射的条目,而 sorting 和 limiting 到 N 个元素将使您更接近您正在寻找的答案。


findMostValuableCustomer

在此 API 中,您希望根据客户各自订单中的最高值来比较客户。所以使用默认的toList下游分组就足够了。

它会通过Map&lt;Customer, List&lt;Order&gt;&gt; 帮助您,您需要在其中从每个客户的所有订单中找到具有max 价格值的条目。

因此,Comparator.comparing(e -&gt; findHighestValueOrder(e.getValue()) 之类的比较器(其中e.getValue()List&lt;Order&gt; customerOrders)可以帮助您解决问题。

我将把findHighestValueOrder 的实施留给你,因为如果你知道如何使用mapflatMap,你只需要在这些订单中找到max 的价格或回退到一些默认值,例如作为BigDecimal.ZERO

【讨论】:

  • 感谢@Naman 您的建议帮助了我。我能够编写代码。
  • 这就是正是 SO的意义所在,恕我直言。
猜你喜欢
  • 2016-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-01-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多