The Java Pills are back! 🎉

🕐 Reading time: 2 minutes

For about a year now I've often been handing small development problems over to AI to optimise my workflow.

Today, for example, I delegated a problem related to data aggregation. I gave the AI the following prompt:

I have a list listA containing objects of type A (a1, a2, …, aN), each one characterised by an identifier id and a list listB. My goal is to aggregate the listB lists for all objects of type A that share the same id.

For example, if a1 and a3 share the same id, their listB elements must be merged. The expected result must be a new list containing a single object of type A for each id, with the aggregated listB.

📌 Why did I choose to delegate the problem to the AI?

Instead of solving it manually (while I was already juggling several tasks in parallel), I chose to hand it straight to the AI. This approach let me:

🔎 An interesting aspect is that I didn't have to provide any domain-specific details: I described the problem in an abstract way (with generic parameters like A and B), avoiding revealing sensitive information about the project. This made the AI's suggestion reusable and generalisable.

📌 The solution proposed by the AI

The AI suggested several solutions, including an implementation based on Java's Stream API and Collectors.groupingBy, perfectly in line with the project's standards (functional style).

The generated code lets you group the objects by their identifier and aggregate the listB lists efficiently. The result is clear, readable, efficient and easily maintainable code. This shows how AI isn't just a tool for writing code, but a valuable support in software development: by assigning it well-defined problems, you can speed up the work, get elegant suggestions and improve the overall quality of the code without losing control over the design decisions.

If you'd rather not modify the original objects but create new ones instead, you can group by id and then merge the lists:

final List<A> mergedList = listA.stream()
        .collect(Collectors.groupingBy(A::getId))
        .entrySet().stream()
        .map(entry -> {
            final Integer id = entry.getKey();
            //merges all the listB lists of the objects with the same id
            final List<B> mergedListB = entry.getValue().stream()
                    .flatMap(a -> a.getListB().stream())
                    .collect(Collectors.toList());
            //creates a new A object with the id and the merged list
            return new A(id, mergedListB);
        })
        .collect(Collectors.toList());

See you at the next pill! ☕