Hook Hook - 9 months ago 74
Java Question

EnumMap & streams

Hi tried to figure out how to map to a EnumMap without success.
At the moment I'm doing it in 2 steps, I create the map and then I make it a EnumMap.
Question are.

  1. Is it possible to do it in only one step?

  2. From efficiency perspective would be better to get Values from
    input, make them a set and then stream it, or just using toMap as
    its right now is correct. thanks

    Map<CarModel, CarBrand> input...
    final Map<CarBrand, CarsSellers> ret = input.values()
    .stream().filter(brand -> !brand.equals(CarBrand.BMW))
    .collect(toMap(Function.identity(), brand -> new CarsSellers(immutableCars, this.carsDb.export(brand))));

    final EnumMap<CarBrand, CarsSellers> enumMap = new EnumMap<>(CarBrand.class);


TL;DR: You need to use the other toMap method.

By default a toMap uses HashMap::new as the Supplier<Map> - you need to supply a new EnumMap instead.

final Map<CarBrand, CarsSellers> ret = input.values()
        .filter(brand -> brand != CarBrand.BMW)
                brand -> new CarsSellers(immutableCars, this.carsDb.export(brand)),
                (l, r) -> {
                    throw new IllegalArgumentException("Duplicate keys " + l + "and " + r + ".");
                () -> new EnumMap<>(CarBrand.class)));

Arguments are:

  1. the key extractor
  2. the value extractor
  3. a "combiner" that takes two values, one that already exists in the Map and one to be added. In this case, we simply throw an IllegalArgumentException as keys should be unique
  4. the "map supplier" - this returns a new EnumMap.

Notes on your code:

  1. program to the interface - Map not EnumMap
  2. enum is singleton, so you can use a != Enum.VALUE
  3. an import static for Function.identity() makes things less verbose