我有以下情况:有一个对象列表-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());
})....;
我知道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
将针对所有元素运行。但是,当您添加filter
时(会忘记peek
做了什么)会发生什么: .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中,根本未调用
peek
。由于您没有使用filter
或flatmap
,因此您无需修改Stream的大小,而count
只需要它的大小即可; 因此根本不调用peek 。因此,依赖peek
是一个非常糟糕的策略。关于java - Java 8窥视与 map ,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/44370676/