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
listAcontaining objects of typeA(a1,a2, …,aN), each one characterised by an identifieridand a listlistB. My goal is to aggregate thelistBlists for all objects of typeAthat share the sameid.For example, if
a1anda3share the sameid, theirlistBelements must be merged. The expected result must be a new list containing a single object of typeAfor eachid, with the aggregatedlistB.
📌 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:
- save time, quickly getting several optimised solutions
- explore more alternatives without having to implement them all by hand
- focus only on choosing and adapting the solution, rather than on writing the code from scratch
🔎 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! ☕