Search code examples
javalambdajava-streammax

Stream.max() on a set of elements from a stream


I have a java List of CodeObj. CodeObj has 2 attributes : codeName and version. My java List looks like this when mapped to a JSON object :

[
    { "codeName": "test1", "version": "1" },

    { "codeName": "test1", "version": "2" },

    { "codeName": "test1", "version": "3" },

    { "codeName": "test2", "version": "1" },

    { "codeName": "test2", "version": "2" },

    { "codeName": "test2", "version": "3" },

    { "codeName": "test2", "version": "4" },
]

I would like to filter this List by each codeName most recent version in java, so it would give this result when mapped to a JSON object :

[
    { "codeName": "test1", "version": "3" },

    { "codeName": "test2", "version": "4" },
]

To make it, I have to use the Stream java class and its methods like filter, map, max, etc.

I started with this bit of code :

codeObjs.stream()
.max(Comparator.comparing(CodeObj::getVersion))

I feel like I have to isolate each set of CodeObj that has the same codeName, but I don't know how to do it while turning the List into a Stream.


Solution

  • return codeObjs.stream()
                .collect(Collectors.groupingBy(
                    CodeObj::getCodeName,
                    Collectors.maxBy(Comparator.comparing(CodeObj::getVersion))
                ))
                .values().stream()
                .flatMap(Optional::stream)
                .collect(Collectors.toList());
    

    So, basically, you are isolating each instance of CodeObj with a unique name by using Collectors.groupingBy. Then using Collectors.maxBy on each group, you get the highest version. Then, by streaming the resulting map, you access collections of Optional<CodeObj> instances, which represent the highest versions per group. flatMap(Optional::stream) transforms these Optionals into a sequence of CodeObj. Finally, you collect them into a list through Collectors.toList()