I'm writing a code to handle Mountain Huts in different municipalities in different provinces. I'm trying to compute the maximum number of beds available in a single mountain hut per altitude range. If the altitude of the mountain hut is not available, i'll use the altitude of its municipality. I would like my method to return a Map<String, Optional<Integer>> but i'm getting a Map <String , Optional<MountainHut>> . Now i am aware of the fact that the Optional i am getting is actually the one who has the maximum bed number but i am struggling to get the right data type.

public Map<String, Optional<Integer>> maximumBedsNumberPerAltitudeRange()
{
    return this.getMountainHuts().stream()
        .collect(
            Collectors.groupingBy((MountainHut mountainHut) ->
                this.getAltitudeRange(
                    mountainHut.getAltitude().orElse(mountainHut.getMunicipality().getAltitude())
                ),
                Collectors.maxBy(Comparator.comparing(MountainHut::getBedsNumber))
            )
        );
}

For completeness i'll post also the getAltitudeRange method, the other methods are just getters.

public String getAltitudeRange(Integer altitude) {
    Range r = ranges.stream()
        .filter((x) -> altitude>= x.getMin() || altitude <= x.getMax())
        .findFirst()
        .orElse(new Range(0,Integer.MAX_VALUE));
    ranges.stream().close();
    if(r.getMax() == Integer.MAX_VALUE)
    {
        return (0 +" - "+ "INF");
    }
    return (r.getMin() + " - " + r.getMax());
}

Altitude is an Optional attribute of the class MountainHut

As expected the error message is the following: Type mismatch: cannot convert from Map> to Map>

1 Answers

1
glee8e On

maxBy doesn't transform, it just compare. Your extracting the key (i.e. bed number) is implementation detail of your Comparator which maxBy has no knowledge of.

You are actually very close though. You just need to add an intermediate step between groupingBy and maxBy.

public Map<String, Optional<Integer>> maximumBedsNumberPerAltitudeRange()
{
    return this.getMountainHuts().stream()
        .collect(
            Collectors.groupingBy((MountainHut mountainHut) ->
                this.getAltitudeRange(
                    mountainHut.getAltitude().orElse(mountainHut.getMunicipality().getAltitude())
                ),
                Collectors.mapping(MountainHut::getBedsNumber, Collectors.maxBy(Comparator.naturalOrder()))
            )
        );
}

PS: In stream heavy classes you can add an import static java.util.stream.Collectors.* to get rid of boilerplate.