Java8Peek与map

Java8Peek与map,java,java-8,Java,Java 8,我有以下情况:有一个对象列表-ProductData,其中包含几个字段: public class ProductData { .... private String name; private String xref; //getters //setters } 还有一个API,它返回以下对象的列表: public class RatingTableRow { private String planName; private String planXref; p

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

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());
        })....;
Map productByXref=plans.stream()
.collect(toMap(ProductData::getInternalCode,Function.identity());
返回getRatingTableRows(…).stream
.filter(ratingRow->productByXref.containsKey(ratingRow.getPlanXref()))
.peek(第行->{
ProductData product=productByXref.get(row.getPlanXref());
row.setPlanName(product.getName());
})....;

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

有一个原因,
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);
您正在对每个元素执行
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中,根本不调用peek。由于您没有使用
过滤器
平面图
,因此您没有修改流的大小,
计数
只需要它的大小因此根本不调用peek。因此,依赖于
peek
是一种非常糟糕的策略

map
forEach
返回行如何?如果要修改现有对象,我认为
foreach
是更好的选择。请解释为什么foreach更适合该任务?因为
foreach
为列表的每个元素应用一些代码,有点像旧式的
for
-循环。但是我只是注意到那些
peek
之后;小溪还有别的地方吗
foreach
是一个终端流操作,因此在这种情况下,
peek
可能确实是最好的方法。顺便说一句,这个方法应该返回什么?嗯,我认为peek在这里并不坏。两者都不映射。需要有人告诉Jetbrains,IntelliJ一直告诉我用
peek
s替换
map
s。真的吗?(我不使用IntelliJ)如果是这样,你应该告诉他们。。。考虑到有这么多聪明人在那里工作,这可能是已知的,或者是一个配置。这可能是因为
map()
方法应该没有副作用,而您返回的是同一个对象?至少对我来说是这样。
您正在为每个元素执行peek,但没有收集任何元素。你确定要这样做吗?
我不明白为什么会有问题,peek在过滤器之前,所以它应该对每个元素执行?@xagaffar:没错。软件逻辑取决于执行顺序。我真的不明白这怎么会让任何人感到惊讶。
    long howMany = Stream.of(1, 2, 3, 4)
            .peek(x -> list.add(x))
            .count();

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