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
。而且无论你修改什么 z
或 b
它最终都会修改源数据
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
我有一个名为 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
。而且无论你修改什么 z
或 b
它最终都会修改源数据
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