Java 8 速览 vs 地图

2022-08-31 16:42:35

我有以下情况:有一个对象列表 - 产品数据,其中包含几个字段:

public class ProductData
{
....
  private String name;
  private String xref;

  //getters
  //setters
}

并且有一个API返回以下对象的列表:

public class RatingTableRow
{
  private String planName;
  private String planXref;
  private int fromAge;
  private int toAge;
  private int ratingRegion;

 //constructor
 //getters
 //setters

}

但它返回具有空计划名称字段的对象,因为在提取此对象期间不允许这样做。我需要通过外部参照将产品数据与 RatingTableRow 链接,以便将计划名称设置为 RatingTableRow,因为我稍后需要使用此对象,因此我创建了以下代码来执行此操作:

Map<String, ProductData> productByXref = plans.stream()
        .collect(toMap(ProductData::getInternalCode, Function.identity()));

return getRatingTableRows(...).stream
        .filter(ratingRow -> productByXref.containsKey(ratingRow.getPlanXref()))
        .peek(row -> {
                ProductData product = productByXref.get(row.getPlanXref());
                row.setPlanName(product.getName());
        })....;

我知道java文档说这不符合这些需求,但希望获得有关如何以更正确的方式完成此任务的建议。peek


答案 1

有一个原因被记录为主要用于调试目的peek

最终在内部处理的内容可能根本不符合终端操作的条件,并且流仅由终端操作执行。peek

首先假设一个简单的例子:

    List<Integer> list = new ArrayList<>();
    List<Integer> result = Stream.of(1, 2, 3, 4)
            .peek(x -> list.add(x))
            .map(x -> x * 2)
            .collect(Collectors.toList());

    System.out.println(list);
    System.out.println(result);

一切看起来都很好吧?因为在这种情况下将针对所有元素运行。但是当你添加一个(并忘记做了什么)时会发生什么:peekfilterpeek

 .peek(x -> list.add(x))
 .map(x -> x * 2)
 .filter(x -> x > 8) // you have inserted a filter here

您正在为每个元素执行,但不收集任何元素。你确定想要那个吗?peek

这可能会变得更加棘手:

    long howMany = Stream.of(1, 2, 3, 4)
            .peek(x -> list.add(x))
            .count();

    System.out.println(list);
    System.out.println(howMany);

在java-8中,列表被填充,但在jdk-9中根本不被调用。由于您没有使用或没有修改流的大小,只需要它的大小;因此,根本不叫偷看。因此,依靠是一个非常糟糕的策略。peekfilterflatmapcountpeek


答案 2

推荐