Reputation: 23
I have a simple POJO called Transaction with three private properties String type,double amount and String id. In main class,I created few instances of Transaction calling the constructor as written below -
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"));
Now I have called below operation on this listusing below code -
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;});
Here I have tried to perform reduction operation by keeping Transaction as the lowest unit and calculate the sum of all transaction amounts and set it inside a new Transaction z. All this gets stored finally as Optional. After this, if I try to carry out any other operation on the transList data source,I get incorrect results as the state of transList gets disrupted.
List<String> transactionIds = transList.stream()
.filter(x -> x.getAmount()>50.00)
.map(Transaction::getId)
.collect(Collectors.toList());
System.out.println(transactionIds);
I have done the Optional containing Double item and double return value implementations successfully for this list using reduce(). All I want to know is what is so wrong with the Optional that it ends up modifying the source of data itself, which should not happen as Stream is functional.
Upvotes: 2
Views: 113
Reputation: 6290
It is everything ok with the Optional. Your object is a reference data type.
Here you copied the reference of your object Transaction z = b;
. It doesn't create a new one. Now both variables point at the same Transaction
. And no matter what you modify z
or b
it ends up modifying the source data
This might be useful https://javarevisited.blogspot.com/2015/09/difference-between-primitive-and-reference-variable-java.html
Upvotes: 0
Reputation: 2773
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
Upvotes: 1
Reputation: 2479
The lambda:
(a,b) -> {Transaction z = b;
z.setAmount(a.getAmount()+b.getAmount());
return z;}
Is modifying the b
parameter. Keep in mind that an assignement does not copy an object so Transaction z = b
is just giving an alias to the object pointed to by b
.
You should probably use the reduce
overload that allows to specify the identity and combiner, os just create a copy of the object.
Upvotes: 3