Валидация списка транзакций относительно баланса

В коде несколько ошибок: ArrayList.add не проверяет повтор ID, баланс не обновляется снаружи isValid, а результат проверки возвращается неверно. Дополнительно Map не может хранить несколько равных Transaction.

Короткий ответ

Что ответить на собеседовании

В коде несколько ошибок: ArrayList.add не проверяет повтор ID, баланс не обновляется снаружи isValid, а результат проверки возвращается неверно. Дополнительно Map не может хранить несколько равных Transaction.

Подробный разбор

Ответ с пояснениями

Условие

Метод проверяет корректность каждой операции. На входе принимает список транзакций и текущий баланс, относительно которого осуществляется проверка. На выходе – карта, где ключом является транзакция, а значением – признак её валидности. Количество элементов во входном списке и в результирующей карте одинаково.

Условия проверки:

  • Транзакции обрабатываются в порядке возрастания их идентификатора id.
  • Если транзакция с определённым id уже была обработана, она считается невалидной.
  • Все транзакции, имеющие тот же orderId, что и уже помеченные как невалидные, также считаются невалидными.
  • Существует два типа операций – UP (увеличивает баланс) и DOWN (уменьшает баланс).
  • Если операция DOWN приводит к отрицательному балансу, такая транзакция считается невалидной.
public class TransactionService {

    public Map<Transaction, Boolean> validate(List<Transaction> transactions, long balance) {
        final var map = new HashMap<Transaction, Boolean>();
        final var ids = new ArrayList<UUID>();
        final var orderIds = new HashSet<Long>();

        for (Transaction transaction : transactions) {
            boolean isValid = false;
            final var orderId = transaction.getOrderId();
            final var isAddId = ids.add(transaction.getId());

            if (isAddId && !orderIds.contains(orderId)) {
                isValid = isValid(transaction, balance);
            }

            if (!isValid) {
                orderIds.add(orderId);
            }

            map.put(transaction, isValid);
        }

        return map;
    }

    public boolean isValid(Transaction transaction, Long balance) {
        final var tempBalance = switch (transaction.getType()) {
            case "UP" -> balance + transaction.getAmount();
            case "DOWN" -> balance - transaction.getAmount();
            default -> balance;
        };

        final var isValid = tempBalance >= 0;

        if (isValid) {
            balance = tempBalance;
        }

        return balance >= 0;
    }

    @Value
    public static class Transaction {
        UUID id;
        long orderId;
        String type;
        long amount;
    }
}

Ответ

В коде несколько ошибок: ArrayList.add не проверяет повтор ID, баланс не обновляется снаружи isValid, а результат проверки возвращается неверно. Дополнительно Map не может хранить несколько равных Transaction.

Нужны сортировка по оговорённому порядку UUID, Set<UUID> обработанных ID и Set<Long> запрещённых orderId. Для каждой операции: отметить ID, проверить тип/положительность amount, вычислить новый баланс через Math.addExact/subtractExact и принять его только при валидности. Невалидный orderId блокирует последующие операции этого заказа. Если блокировка должна быть ретроактивной, нужен отдельный пересчёт. Гарантия одинакового размера списка и Map противоречива при равных @Value-объектах: лучше вернуть List<Result> с индексом исходного элемента либо запретить такие входы.

ИИ-помощник для собеседований

Хочешь уверенно проходить собеседования?

Попробуй ИИ-помощник для собеседований: слышит вас и собеседника, анализирует экран, подсказывает ответы в реальном времени, работает без VPN и не попадает в захват экрана.

Подробнее