在Java 8中合并多个映射

时间:2017-11-05 00:58:29

标签: java dictionary collections java-8

Java 8在这里。我有以下课程:

public interface Animal {
  ...
}

public class Dog implements Animal {
  ...
}

public class Cat implements Animal {
  ...
}

public class Elephant implements Animal {
  ...
}

我必须实现以下方法:

void doSomething(Map<String,Dog> dogs, Map<String,Cat> cats, Map<String,Elephant> elephants) {
  // TODO:
  // * Merge all dogs, cats & elephants together into the same Map<String,Animal>,
  //     but...
  // * Do so generically (without having to create, say, a HashMap instance, etc.)
}

在我的doSomething(...)方法中,我需要将所有地图参数合并到同一个Map<String,Animal>地图中,我真的更愿意这样做而不用< strong>我的代码必须实例化特定的地图实现(例如HashMap等)。

意思是,我知道我可以这样做:

void doSomething(Map<String,Dog> dogs, Map<String,Cat> cats, Map<String,Elephant> elephants) {
  Map<String,Animal> animals = new HashMap<>();
  for(String dog : dogs.keySet()) {
    animals.put(dog, dogs.get(dog));
  }
  for(String cat : cats.keySet()) {
    animals.put(cat, cats.get(cat));
  }
  for(String elephant : elephants.keySet()) {
    animals.put(elephant, elephants.get(elephant));
  }

  // Now animals has all the argument maps merged into it, but is specifically
  // a HashMap...
}

我甚至可以使用一些实用程序(如果它存在),例如Collections.merge(dogs, cats, elephants)等等。任何想法?

3 个答案:

答案 0 :(得分:5)

这样做的一种方法是创建一组条目流,然后将其平面映射以获得条目流并将其收集到地图中。

Map<String,Animal> animals = 
    Stream.of(dogs.entrySet(), cats.entrySet(), elephants.entrySet())
          .flatMap(Set::stream)
          .collect(toMap(Map.Entry::getKey, Map.Entry::getValue));

//Stream.of(dogs, cats, elephants).flatMap(m -> m.entrySet().stream()) could also be an option

也不是使用Map#putAll的单行且没有流:

Map<String,Animal> animals = new HashMap<>(dogs);
animals.putAll(cats);
animals.putAll(elephants);

答案 1 :(得分:2)

您可以使用Stream.Concat

完成手头的任务
Map<String,Animal> animals = Stream.concat(Stream.concat(dogs.entrySet().stream(), cats.entrySet().stream()), elephants.entrySet().stream())
                                   .collect(Collectors.toMap
                                    (
                                       Map.Entry::getKey,
                                       Map.Entry::getValue
                                    )
                              );

你需要在这里保持谨慎,因为合并时有重复的密钥,然后会按预期引发异常。

答案 2 :(得分:1)

IMO的最佳方式与Alexis C.'s answer一样Map.putAll

Map<String, Animal> animals = new HashMap<>(dogs);
animals.putAll(cats);
animals.putAll(elephants);

这一个的变体:

Map<String, Animal> animals = new HashMap<>(dogs);
cats.forEach(animals::put);
elephants.forEach(animals::put);