Операция Reduce () в потоке, похоже, изменяет источник данных (список) Stream API Java 8 - PullRequest
0 голосов
/ 08 февраля 2019

У меня есть простой POJO под названием Транзакция с тремя частными свойствами: тип String, удвоенная сумма и идентификатор String.В основном классе я создал несколько экземпляров 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;});

Здесь у меня естьпопытался выполнить операцию сокращения, сохранив Транзакцию как наименьшую единицу, рассчитав сумму всех сумм транзакции и установив ее внутри новой транзакции z.Все это в конечном итоге сохраняется как необязательное.После этого, если я пытаюсь выполнить любую другую операцию с источником данных transList, я получаю неверные результаты, поскольку состояние transList нарушается.

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

Я выполнил опциональный элемент Double, содержащий двойной возвратреализации значений успешно для этого списка с помощью Redu ().Все, что я хочу знать, это то, что не так с Optional, что он в конечном итоге изменяет сам источник данных, что не должно происходить, так как Stream работает.

Ответы [ 3 ]

0 голосов
/ 08 февраля 2019

С опциональным все в порядке.Ваш объект является ссылочным типом данных.Здесь вы скопировали ссылку вашего объекта Transaction z = b;.Это не создает новый.Теперь обе переменные указывают на один и тот же Transaction.И независимо от того, что вы изменяете z или b, в конечном итоге это приводит к изменению исходных данных

Это может быть полезно https://javarevisited.blogspot.com/2015/09/difference-between-primitive-and-reference-variable-java.html

0 голосов
/ 08 февраля 2019
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 
0 голосов
/ 08 февраля 2019

Лямбда:

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

Изменяет параметр b.Имейте в виду, что присвоение не копирует объект, поэтому Transaction z = b просто присваивает псевдоним объекту, указанному b.

Вы, вероятно, должны использовать reduceПерегрузка, позволяющая указать личность и объединитель, либо просто создать копию объекта.

...