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

时间:2019-02-08 08:35:13

标签: java java-8 java-stream pass-by-reference reduce

我有一个名为Transaction的简单POJO,具有三个私有属性String type,double amount和String id。 在主类中,我创建了一些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中来执行缩减操作。最后,所有这些都作为可选存储。 此后,如果我尝试对transList数据源执行任何其他操作,由于transList的状态被破坏,我会得到错误的结果。

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

我已经使用reduce()成功完成了此列表的Optional包含Double项目和double返回值的实现。 我只想知道Optional到底有什么问题,以至于它最终修改了数据源本身,因为Stream功能正常,所以这不会发生。

3 个答案:

答案 0 :(得分:3)

lambda:

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

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

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

答案 1 :(得分:1)

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 

答案 2 :(得分:0)

使用Optional没关系。您的对象是参考数据类型。 在这里,您复制了对象Transaction z = b;的引用。它不会创建一个新的。现在,两个变量都指向相同的Transaction。而且无论您修改z还是b,都将最终修改源数据

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