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.

    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(

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<>()


        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) {