Search code examples
javahashmapjava-streamgroupingby

Convert a Map<T, Value> to a List<T> based on parameter of the object and value


I have a map Map<MetricResult, Long> metricResultToComputationTime.

MetricResult has a method MetricResult::getEndTime.

I want to get a List<MetricResult> where every MetricResult has a unique end time. If end times match, I want to use the one with the greater computation time from the map. How do I do this neatly?

I know there are simple wordy ways to do this, but I'm looking for something elegant.

I tried some stuff like this:

List<MetricResult> metricResults =
    metricResultToComputationTime.entrySet().stream()
        .collect(
            groupingBy(
                MetricResult::getEndTime,
                collectingAndThen(maxBy(Map.Entry.comparingByValue()), Optional::get)))
        .values();

But it doesn't compile

Error:

no suitable method found for collect(java.util.stream.Collector<MetricResult&java.util.Map.Entry<java.lang.Object,V>,capture#1 of ?,java.util.Map<Timestamp,java.lang.Object>>) method java.util.stream.Stream.collect(java.util.function.Supplier,java.util.function.BiConsumer<R,? super java.util.Map.Entry<MetricResult,Timestamp>>,java.util.function.BiConsumer<R,R>) is not applicable (inference variable T has incompatible bounds upper bounds: MetricResult,java.util.Map.Entry<K,V>,T,T lower bounds: MetricResult,Timestamp>)


Solution

  • Minor modifications:

    1. Change MetricResult::getEndTime to obtain endTime from entry: ent -> ent.getKey().getEndTime().
    2. Map grouped entry results to a list with values().stream().map(Map.Entry::getKey).toList().
    List<MetricResult> metricResults =
        metricResultToComputationTime.entrySet().stream()
            .collect(groupingBy(
                ent -> ent.getKey().getEndTime(),
                collectingAndThen(maxBy(Map.Entry.comparingByValue()), Optional::get)))
            .values().stream()
            .map(Map.Entry::getKey).toList();