You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将多个List<DTO1>的数据合并到单个List<DTO2>中?

Merge List Collections into List

Hey there! Let's work through this problem together. It looks like you need to combine three List<DTO1> collections (ListA, ListB, ListC) into a single List<DTO2>, where each DTO2 entry captures the count values from each source list tied to the same id and userLogin pair. Here's a straightforward, effective way to do this:

Step 1: Confirm DTO Definitions

First, let's align on the DTO structures you mentioned. I'll assume they look like this (adjust getters/setters or constructors as needed for your codebase):

// DTO1: Contains the source data
public class DTO1 {
    private Long id;
    private String userLogin;
    private Integer count;

    // Getters, Setters, and Constructor(s)
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getUserLogin() { return userLogin; }
    public void setUserLogin(String userLogin) { this.userLogin = userLogin; }
    public Integer getCount() { return count; }
    public void setCount(Integer count) { this.count = count; }
}

// DTO2: The target structure with count fields for each source list
public class DTO2 {
    private Long id;
    private String userLogin;
    private Integer countListA;
    private Integer countListB;
    private Integer countListC;

    // Getters, Setters, and Constructor(s)
    public Long getId() { return id; }
    public void setId(Long id) { this.id = id; }
    public String getUserLogin() { return userLogin; }
    public void setUserLogin(String userLogin) { this.userLogin = userLogin; }
    public Integer getCountListA() { return countListA; }
    public void setCountListA(Integer countListA) { this.countListA = countListA; }
    public Integer getCountListB() { return countListB; }
    public void setCountListB(Integer countListB) { this.countListB = countListB; }
    public Integer getCountListC() { return countListC; }
    public void setCountListC(Integer countListC) { this.countListC = countListC; }
}

Step 2: Merge Logic Using a Map

The key here is to group entries by their unique id + userLogin pair, then populate the corresponding count fields in DTO2. We'll use a Map to track these pairs and build our DTO2 objects incrementally:

import java.util.*;
import java.util.function.BiConsumer;

public class DtoMerger {
    public List<DTO2> mergeDtoLists(List<DTO1> listA, List<DTO1> listB, List<DTO1> listC) {
        // Map to hold DTO2 entries, keyed by (id, userLogin) pair
        Map<Map.Entry<Long, String>, DTO2> dto2Map = new HashMap<>();

        // Populate the map with each source list, setting the correct count field
        populateDtoMap(listA, dto2Map, DTO2::setCountListA);
        populateDtoMap(listB, dto2Map, DTO2::setCountListB);
        populateDtoMap(listC, dto2Map, DTO2::setCountListC);

        // Convert the map values to our final List<DTO2>
        return new ArrayList<>(dto2Map.values());
    }

    // Helper method to handle populating the map from a single source list
    private void populateDtoMap(List<DTO1> sourceList, 
                               Map<Map.Entry<Long, String>, DTO2> dto2Map,
                               BiConsumer<DTO2, Integer> countSetter) {
        for (DTO1 dto1 : sourceList) {
            // Create a unique key from id and userLogin
            Map.Entry<Long, String> key = new AbstractMap.SimpleEntry<>(dto1.getId(), dto1.getUserLogin());
            
            // Create a new DTO2 if this key doesn't exist yet, initialize base fields
            dto2Map.computeIfAbsent(key, k -> {
                DTO2 dto2 = new DTO2();
                dto2.setId(k.getKey());
                dto2.setUserLogin(k.getValue());
                // Initialize counts to null (or 0 if you prefer default values)
                dto2.setCountListA(null);
                dto2.setCountListB(null);
                dto2.setCountListC(null);
                return dto2;
            });

            // Set the count value for the current source list
            countSetter.accept(dto2Map.get(key), dto1.getCount());
        }
    }
}

How This Works

  • Unique Key: We use Map.Entry<Long, String> as the map key to represent the unique combination of id and userLogin. This ensures we group all entries that belong to the same user/id pair.
  • Lazy Initialization: computeIfAbsent creates a new DTO2 only when we first encounter a key, setting up the base id and userLogin values.
  • Count Population: The helper method uses a BiConsumer to set the correct count field (countListA, countListB, or countListC) based on which source list we're processing.
  • Handling Missing Entries: If a user/id pair doesn't exist in one of the source lists, the corresponding count field will stay null (you can change this to 0 in the initialization step if needed).

Optional: Stream-Based Approach

If you prefer using Java Streams for a more declarative style, here's an alternative implementation:

import java.util.*;
import java.util.stream.Collectors;
import java.util.stream.Stream;

public class StreamDtoMerger {
    public List<DTO2> mergeWithStreams(List<DTO1> listA, List<DTO1> listB, List<DTO1> listC) {
        // Combine all source entries with a tag indicating which list they came from
        Stream<Map.Entry<DTO1, String>> taggedEntries = Stream.concat(
                listA.stream().map(dto -> new AbstractMap.SimpleEntry<>(dto, "A")),
                Stream.concat(
                        listB.stream().map(dto -> new AbstractMap.SimpleEntry<>(dto, "B")),
                        listC.stream().map(dto -> new AbstractMap.SimpleEntry<>(dto, "C"))
                )
        );

        // Group by id+userLogin, then build DTO2 from grouped entries
        return taggedEntries.collect(Collectors.groupingBy(
                        entry -> new AbstractMap.SimpleEntry<>(entry.getKey().getId(), entry.getKey().getUserLogin()),
                        Collectors.collectingAndThen(Collectors.toList(), entries -> {
                            DTO2 dto2 = new DTO2();
                            DTO1 firstDto = entries.get(0).getKey();
                            dto2.setId(firstDto.getId());
                            dto2.setUserLogin(firstDto.getUserLogin());

                            // Populate counts based on the source tag
                            entries.forEach(entry -> {
                                switch (entry.getValue()) {
                                    case "A":
                                        dto2.setCountListA(entry.getKey().getCount());
                                        break;
                                    case "B":
                                        dto2.setCountListB(entry.getKey().getCount());
                                        break;
                                    case "C":
                                        dto2.setCountListC(entry.getKey().getCount());
                                        break;
                                }
                            });
                            return dto2;
                        })
                ))
                .values()
                .stream()
                .collect(Collectors.toList());
    }
}

Notes

  • Duplicate Entries: If a user/id pair appears multiple times in a single source list, both implementations will use the last encountered count value. If you need to sum counts instead, modify the logic to add to the existing value instead of overwriting it.
  • Lombok: To reduce boilerplate code, consider using Lombok's @Data annotation on your DTO classes to auto-generate getters, setters, and constructors.

内容的提问来源于stack exchange,提问作者sina ardehali

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.19 07:55:16