Java 8+: Using Collectors as reducers

A simple example to show how to use Collectors as reducers in Java 8+.

Say, we have a simple Transaction class consists of the currency and the value of the transaction.

Transaction class is sprinkled with Lombok annotation to make use of Builder.

    @Value
    @Builder
    public static class Transaction {
        String currency;
        int value;
    }

And given the following set of data:

GBP Transactions = 2, USD Transactions = 1, CAD Transactions = 1

    List<Grouping.Transaction> transactionList = List.of(
            Grouping.Transaction.builder().currency("GBP").value(1).build(),
            Grouping.Transaction.builder().currency("GBP").value(5).build(),
            Grouping.Transaction.builder().currency("USD").value(6).build(),
            Grouping.Transaction.builder().currency("CAD").value(9).build()
    );

We would like to group this list by transaction currency, so that

    assertEquals(transactionsByCurrency.get("GBP").size(), 2);
    assertEquals(transactionsByCurrency.get("USD").size(), 1);
    assertEquals(transactionsByCurrency.get("CAD").size(), 1);

Here are the two approaches to implement this requirement.

    public Map<String, List<Transaction>> imperative(List<Transaction> transactionList) {
        Map<String, List<Transaction>> transactionsByCurrency = new HashMap<>();

        for (Transaction transaction: transactionList) {
            List<Transaction> transactionForCurrency = transactionsByCurrency.computeIfAbsent(
                    transaction.getCurrency(), k -> new ArrayList<>()
            );

            transactionForCurrency.add(transaction);
        }

        return transactionsByCurrency;
    }

And let’s compare that to using Streams and Collectors which ended up a lot less verbose and simple to understand.

    public Map<String, List<Transaction>> functional(List<Transaction> transactionList) {
        return transactionList.stream()
                .collect(
                        Collectors.groupingBy(Transaction::getCurrency)
                );
    }