我有一个名为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