流上的reduce()操作似乎正在修改数据源(列表)stream API Java 8



我有一个名为Transaction的简单POJO,它有三个私有属性String type、double amount和String id。在main类中,我创建了一些Transaction实例,调用如下所述的构造函数-

List<Transaction> transList = Arrays.asList(new Transaction(Transaction.TRANSACTION_TYPE_GROCERY,45.50,"2a"),
new Transaction(Transaction.TRANSACTION_TYPE_GROCERY,50.0,"1a"),
new Transaction(Transaction.TRANSACTION_TYPE_GROCERY,15.00,"3a"),
new Transaction(Transaction.TRANSACTION_TYPE_GROCERY,27.43,"4a"),
new Transaction(Transaction.TRANSACTION_TYPE_CLOTHING,145.0,"5a"),
new Transaction(Transaction.TRANSACTION_TYPE_CLOTHING,105.0,"6a"));

现在我已经使用下面的代码调用了这个列表上的以下操作-

Optional<Transaction> totalA = transList.stream()
.filter(x->x.getType()==Transaction.TRANSACTION_TYPE_GROCERY)
.reduce((a,b) -> {Transaction z = b;                                                                             
z.setAmount(a.getAmount()+b.getAmount());
return z;});

在这里,我试图通过将Transaction作为最低单位来执行减少操作,并计算所有交易金额的总和,并将其设置在新的Transaction z中。所有这些最终都存储为Optional。在此之后,如果我试图对transList数据源执行任何其他操作,我会得到不正确的结果,因为transList的状态会被打乱。

List<String> transactionIds = transList.stream()
.filter(x -> x.getAmount()>50.00)
.map(Transaction::getId)
.collect(Collectors.toList());
System.out.println(transactionIds);

我已经使用reduce()成功地为该列表实现了包含Double项和双返回值的Optional。我只想知道Optional到底出了什么问题,以至于它最终修改了数据源本身,这不应该发生在Stream正常工作时。

λ:

(a,b) -> {Transaction z = b;                                                                             
z.setAmount(a.getAmount()+b.getAmount());
return z;}

正在修改b参数。请记住,赋值不会复制对象,因此Transaction z = b只是为b指向的对象提供一个别名。

您可能应该使用允许指定标识和组合器的reduce重载,或者只创建对象的副本。

Transaction z = b;// doesn't create a new object.  
z.setAmount(a.getAmount()+b.getAmount()); //you actually set a amout to `b` object
return z; // and here you returm `b` object 

使用Optional一切正常。您的对象是引用数据类型。在这里,您复制了对象Transaction z = b;的引用。它不会创建一个新的。现在两个变量都指向同一个Transaction。无论你修改z还是b,它最终都会修改源数据

这可能很有用https://javarevisited.blogspot.com/2015/09/difference-between-primitive-and-reference-variable-java.html

最新更新