Search code examples
javacollectionsjava-streamlogic

Java Stream API, Collect result into Map<code, concatenated string> from a List containing two separate lists


Here is the code which need to generate the output as follows using Stream API.

Input:

[Subgroup(id=1, names=[Name(languageCode=1, longName=ABD), Name(languageCode=2, longName=BD)], level=Level(names=[Names(languages=1, longName=1 1), Names(languages=2, longName=2 2)]))]

Output:

Map:{1=ABD~1 1, 2=BD~2 2}

Java-6: Code which generates the required output. but, we need to use Stream API and collect the output because the Sample input i am providing only single obj. Where in realtime i am having more than 50 objects. So, i need it in Advanced version of Java.

public class SubgroupProcessor {
    public static void main(String[] args) {
        List<Name> names = Arrays.asList(new Name(1, "ABD"), new Name(2, "BD"));
        List<Names> namesLevel = Arrays.asList(new Names(1, "1 1"), new Names(2, "2 2"));
        List<Subgroup> subgroups = Arrays.asList(new Subgroup(1, names, new Level(namesLevel)));
        System.out.println(subgroups);

        Map<Integer, String> map = new HashMap<>();
        for (Subgroup subgroup : subgroups) {
            List<Name> names2 = subgroup.getNames();
            List<Names> namesLevel2 = subgroup.getLevel().getNames();
            for (Name name : names2) {
                for (Names nameLevel : namesLevel2) {
                    if (nameLevel.getLanguages() == name.getLanguageCode()) {
                        map.put(name.getLanguageCode(), name.getLongName() + "~" + nameLevel.getLongName());
                    }
                }
            }
        }
        System.out.println("Map:"+map);
    }
}

@Data @AllArgsConstructor
class Subgroup {
    private int id;
    private List<Name> names;
    private Level level;
}

@Data @AllArgsConstructor
class Name {
    private int languageCode;
    private String longName;
}

@Data @AllArgsConstructor
class Names {
    private int languages;
    private String longName;
}

@Data @AllArgsConstructor
class Level {
    private List<Names> names;
}

Tried Chat-GPT as well but generated the following code and its not working.

This code uses Java 8 streams to process the input list and produce the required output in the form of a map with language codes as keys and concatenated names as values.

Map<Integer, String> map = subgroups.stream()
    .flatMap(subgroup -> subgroup.getNames().stream()
            .filter(name -> getMatching(subgroup, name))
            .map(name -> Map.entry(name.getLanguageCode(), name.getLongName() + "~" + getLevelLongName(subgroup, name)))
    )
    .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));
    

public static boolean getMatching(Subgroup sg, Name name) {
    return sg.getLevel().getNames().stream()
            .anyMatch(ln -> ln.getLanguages() == name.getLanguageCode());
}

private static String getLevelLongName(Subgroup subgroup, Name name) {
    return subgroup.getLevel().getNames().stream()
            .filter(levelName -> levelName.getLanguages() == name.getLanguageCode())
            .map(Names::getLongName)
            .findFirst()
            .orElse("");
}

Solution

  • You may try something like this instead:

    Map<Integer, String> result = subgroups.stream()
            .flatMap(subgroup -> 
                subgroup.getNames().stream()
                    .map(name -> new AbstractMap.SimpleEntry<>(
                        name.getLanguageCode(), 
                        name.getLongName() + "~" + 
                            subgroup.getLevel().getNames().stream()
                                .filter(levelName -> levelName.getLanguages() == name.getLanguageCode())
                                .map(Names::getLongName)
                                .findFirst()
                                .orElse("")))
            )
            .collect(Collectors.toMap(Map.Entry::getKey, Map.Entry::getValue));