1

I have the following method to map values in map:

public static <X, Y, Z> Map<X, Z> transformValues(Map<? extends X, ? extends Y> input, Function<Y, Z> function) {
    return input.keySet().stream()
      .collect(Collectors.toMap(Function.identity(),
        key -> function.apply(input.get(key))));
  }

It was suggested here: https://stackoverflow.com/a/25905196/411965

I want to create a similar method to SortedMap:

public static <X, Y, Z> SortedMap<X, Z> transformValues(SortedMap<? extends X, ? extends Y> input, Function<Y, Z> function)

What is the way to do that with java 8?

oshai
  • 14,865
  • 26
  • 84
  • 140
  • 2
    The `Collectors` utility class provides a `toMap` overload that allows you to parametrize with a `Supplier` for your desired `Map` type - see [here](https://docs.oracle.com/javase/8/docs/api/java/util/stream/Collectors.html#toMap-java.util.function.Function-java.util.function.Function-java.util.function.BinaryOperator-java.util.function.Supplier-). – Mena Nov 06 '18 at 15:47

2 Answers2

2

You could collect into a TreeMap that implements SortedMap.

public static <X, Y, Z> SortedMap<X, Z> transformValues(Map<? extends X, ? extends Y> input, Function<Y, Z> function) {
    return input.keySet()
                .stream()
                .collect(Collectors.toMap(Function.identity(),
                                          key -> function.apply(input.get(key)),
                                          (v1, v2) -> {
                                              return v1;
                                          }, TreeMap::new));

}
davidxxx
  • 125,838
  • 23
  • 214
  • 215
1

Al alternate solution without streams:

SortedMap<X, Z> output = new TreeMap<>();
input.forEach((x, y) -> output.put(x, function.apply(y)));

This approach doesn't iterate over the keyset to later perform a lookup for each key. Instead, it iterates the map directly and puts each key-value pair in the output SortedMap, using function to previously transform the values. It is also more succinct and readable, IMO.

fps
  • 33,623
  • 8
  • 55
  • 110