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

reduce() operation on stream seems to be modifying the source of data (list) Stream API Java 8

我有一个名为 Transaction 的简单 POJO,它具有三个私有属性 String type、double amount 和 String id。 在 main class 中,我创建了几个调用构造函数的 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() 为该列表成功完成了包含双项和双 return 值的可选实现。 我只想知道 Optional 有什么问题,它最终修改了数据源本身,这不应该发生,因为 Stream 是功能性的。

拉姆达:

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

正在修改b参数。请记住,赋值 不会 复制一个对象,因此 Transaction z = b 只是给 b.

指向的对象一个别名

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

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

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

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