Java hashmap or List for aggregate function

I have result set data coming back from DB as follows: Input looks like this. Its an arrayList

id  year    name    rank      Subj      Marks   
1   2025    name1   A       Science     90
1   2025    name1   A       History     90
1   2025    name1   A       Math        90
2   2025    name2   A       Science     80
2   2025    name2   A       History     80
2   2025    name2   A       Math        80

Output should look like this

id    year  name    rank      Subj      Marks   
1   2025    name1   A       Subject     270
2   2025    name2   A       Subject     240

This would be having 1500 records minimum so which would be efficient. What i was thinking is looping the list and putting them to hashMap. Then iterate maps with same id’s and sum the marks property.

Is there an efficient way to do this?

HashMap<String, Object> hmDto = new HashMap<String, Object>();
for (ABCDTO obj : list)
{
    ResultsBean bean = new ResultsBean();
    hmDto.put(obj.getId(), bean);

}

and then iterate the hashmap and sum the marks. Finally add cummulated data to another list

HashMap<String, Object> hmCalDto = new HashMap<String, Object>();
for (Map.Entry<String, Object> entry : hmDto .entrySet()) {
    List<ABCDTO> dtoTempList = new ArrayList();
    ABCDTO obj = (ABCDTO) entry.getValue();
    if (hmDto.containsKey(entry.getKey())) {
        dtoTempList.add(obj);                   
    } else {
        continue;
    }
    hmCalDto.put(entry.getKey(), obj);
}

I am lost on how to do this further. Is there an efficient way to do this please.

Yes, there’s a much cleaner and efficient way to do this.

You are on the right track using a Map keyed by a unique identifier (like id) to group and sum the data, but your implementation has some confusion and unnecessary steps.

Let me show you how to do it step-by-step in a straightforward and efficient way:


1. Define your DTO (example):

public class ABCDTO {
    private int id;
    private int year;
    private String name;
    private String rank;
    private String subject;
    private int marks;

    // Getters and setters
}

2. Define a result class for the aggregated output:

public class ResultsBean {
    private int id;
    private int year;
    private String name;
    private String rank;
    private String subject = "Subject"; // fixed
    private int totalMarks;

    // Constructor
    public ResultsBean(int id, int year, String name, String rank) {
        this.id = id;
        this.year = year;
        this.name = name;
        this.rank = rank;
    }

    public void addMarks(int marks) {
        this.totalMarks += marks;
    }

    // Getters and setters
}

3. Process the input list and generate the output:

public List<ResultsBean> aggregateResults(List<ABCDTO> inputList) {
    Map<Integer, ResultsBean> resultsMap = new HashMap<>();

    for (ABCDTO dto : inputList) {
        int id = dto.getId();
        ResultsBean bean = resultsMap.get(id);

        if (bean == null) {
            bean = new ResultsBean(dto.getId(), dto.getYear(), dto.getName(), dto.getRank());
            resultsMap.put(id, bean);
        }

        bean.addMarks(dto.getMarks());
    }

    return new ArrayList<>(resultsMap.values());
}

4. Why this is efficient

  • Single pass through the input list (O(n))
  • No unnecessary intermediate lists or map iterations
  • Memory efficient: you’re storing only one ResultsBean per unique id

Example input:

List<ABCDTO> input = Arrays.asList(
    new ABCDTO(1, 2025, "name1", "A", "Science", 90),
    new ABCDTO(1, 2025, "name1", "A", "History", 90),
    new ABCDTO(1, 2025, "name1", "A", "Math", 90),
    new ABCDTO(2, 2025, "name2", "A", "Science", 80),
    new ABCDTO(2, 2025, "name2", "A", "History", 80),
    new ABCDTO(2, 2025, "name2", "A", "Math", 80)
);

Calling aggregateResults(input) would give you:

[
  { id=1, year=2025, name="name1", rank="A", subject="Subject", totalMarks=270 },
  { id=2, year=2025, name="name2", rank="A", subject="Subject", totalMarks=240 }
]

Let me know if you want to do the same thing using Java 8 streams.