英文:
Convert List of objects to nested ordered map of ordered lists
问题
最终的Map<String, Map<String, Map<String, ArrayList<String>>> collect =
    dtoList.stream()
        .collect(
            Collectors.groupingBy(
                Dto::getValidationType,
                Collectors.groupingBy(
                    Dto::getSource,
                    Collectors.groupingBy(
                        Dto::getAddress,
                        Collector.of(
                            TreeSet::new, 
                            (set, dto) -> set.add(dto.getError()), 
                            (set1, set2) -> { set1.addAll(set2); return set1; },
                            ArrayList::new
                        )
                    )
                )
            )
        );
英文:
I want to convert a list of DTOs into a deep nested map.
Source format:
[
    Dto(validationType=BASIC, source=BASE, address=A4, error=Client is a required field.),
    Dto(validationType=BASIC, source=BASE, address=A4, error=Client must be one of 'I', 'G' or 'W'.),
    Dto(validationType=BASIC, source=BASE, address=B5, error=Individuals require First and Last Names.),
    Dto(validationType=BASIC, source=BASE, address=D6, error=Individuals require First and Last Names.),
    Dto(validationType=BASIC, source=BASE, address=J7, error=First is a required field.),
    Dto(validationType=BASIC, source=BASE, address=L8, error=Last is a required field.),
    Dto(validationType=BASIC, source=BASE, address=M9, error=Name is a required field.),
    Dto(validationType=BASIC, source=BASE, address=N10, error=Status is a required field.),
    Dto(validationType=BASIC, source=BASE, address=N10, error=Status must be one of 'A' or 'P'.),
    Dto(validationType=BASIC, source=BASE, address=F16, error=Groups require a Group Name.)
]
Target format:
{
    BASIC = {
        BASE = {
            A4 = [ "Client is a required field.", "Client must be one of 'I', 'G' or 'W'." ],
            B5 = [ "Individuals require First and Last Names." ],
            D6 = [ "Individuals require First and Last Names." ],
            J7 = [ "First is a required field." ],
            L8 = [ "Last is a required field." ],
            M9 = [ "Name is a required field." ],
            N10 = [ "Status is a required field." ],
            N10 = [ "Status must be one of 'A' or 'P'." ],
            F16 = [ "Groups require a Group Name." ]
        }
    }
}
This code snippet:
final Map<String, Map<String, Map<String, ArrayList<String>>>> collect =
    dtoList.stream()
        .collect(
            Collectors.groupingBy(
                Dto::getValidationType,
                Collectors.groupingBy(
                    Dto::getSource,
                    Collectors.groupingBy(
                        Dto::getAddress,
                        Collectors.mapping(
                            Dto::getError,
                            Collectors.collectingAndThen(
                                Collectors.toSet(),
                                ArrayList::new))))));
produces this map:
{
    BASIC = {
        BASE = {
key       ->            D6 = [ "Individuals require First and Last Names."],
order     ->            B5 = [ "Individuals require First and Last Names.],
not       ->            A4 = [ "Client must be one of 'I', 'G' or 'W'.", "Client is a required field."], <- values' original order lost
preserved ->            F16 = [ "Groups require a Group Name." ],
          ->            N10 = [ "Status must be one of 'A' or 'P'.", "Status is a required field." ],
          ->            M9 = [ "Name is a required field." ],
          ->            L8 = [ "Last is a required field." ],
          ->            J7 = [ "First is a required field." ]
        }
    }
}
The problems are:
- The keys under BASE are not sorted. I know I need something like a TreeSet, but I am not sure how to collect into such a collection.
 - The values within each list are not preserving their order. "Client is a required field." should come before "Client must be one of 'I', 'G' or 'W'.", because that is their original order.
 
答案1
得分: 1
你需要传入`Supplier` `mapFactory`来指定你想要收集的`Map`类型(`()->new TreeMap<>()`)。对于`TreeSet`也是一样的。
最终的`TreeMap<String, TreeMap<String, TreeMap<String, TreeSet<String>>>> collect =
            list.stream()
                .collect(
                    groupingBy(
                        Dto::getValidationType,
                        TreeMap::new,
                        groupingBy(
                            Dto::getSource,
                            TreeMap::new,
                            groupingBy(
                                Dto::getAddress,
                                TreeMap::new,
                                Collectors.mapping(
                                    Dto::getError,
                                    Collectors.collectingAndThen(
                                        Collectors.toSet(),
                                        TreeSet::new)
                                )
                            )
                        )
                    )
                );`
英文:
You need to pass in the Supplier mapFactory to specify the type of Map you wish to collect in (()->new TreeMap<>()). Same in case of TreeSet
    final TreeMap<String, TreeMap<String, TreeMap<String, TreeSet<String>>>> collect =
        list.stream()
            .collect(
                groupingBy(
                    Dto::getValidationType,
                    TreeMap::new,
                    groupingBy(
                        Dto::getSource,
                        TreeMap::new,
                        groupingBy(
                            Dto::getAddress,
                            TreeMap::new,
                            Collectors.mapping(
                                Dto::getError,
                                Collectors.collectingAndThen(
                                    Collectors.toSet(),
                                    TreeSet::new)
                            )
                        )
                    )
                )
            );
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论