【问题标题】:Java invert a mapJava反转地图
【发布时间】:2016-12-06 23:29:53
【问题描述】:

我需要反转原始地图。哪个类型是<Integer, String>,比如{1 = A, 2 = A, 3 = B....}。我想创建一个从StringArrayList 的新地图,因为如果1 = A2 = A,我想要这样的东西:A = [1, 2]

那我该怎么做呢?

【问题讨论】:

标签: java arraylist hashmap


【解决方案1】:

您可以使用 Java 8 的 stream API 轻松做到这一点,下面是一个示例:

public static void main(String[] args) throws FileNotFoundException {

    Map<Integer, String> map = new HashMap<>();
    map.put(1, "A");
    map.put(2, "A");
    map.put(3, "B");

    Map<String, List<Integer>> invertedMap = map.entrySet()
    .stream()
    .collect(Collectors.groupingBy(Entry::getValue, 
            Collectors.mapping(Entry::getKey, Collectors.toList())));

    System.out.println(invertedMap);

}

【讨论】:

  • 我真的不明白为什么人们更喜欢使用流方法来解决这样的问题。这似乎是不直观的非自我记录代码。这比传统的循环示例有什么好处?
  • 我不会投反对票,因为它没有错,但我会在代码审查中反弹。很难弄清楚代码在做什么,如果你的需求发生了变化,就没有办法改变它,你必须完全重写它。
  • 这里的普遍共识是,如果 Java 已经为某些东西提供了库/API,我宁愿使用它而不是编写我自己的样板代码(无论如何它都不会像 Java 的本机 API 那样高效)。
【解决方案2】:

你可以试试这个:

HashMap<Integer, String> original = new HashMap<>();
HashMap<String, ArrayList<Integer>> inverted = new HashMap<>();

original.put(1, "A");
original.put(2, "B");
original.put(3, "C");
original.put(4, "A");

for (Integer key: original.keySet()) {
    String newKey = original.get(key);

    inverted.computeIfAbsent(newKey, k -> new ArrayList<>());
    inverted.get(newKey).add(key);

}
System.out.println(original);
System.out.println(inverted);

所以,假设HashMap&lt;Integer, String&gt; original{1=A, 2=B, 3=C, 4=A},那么你将得到{A=[1, 4], B=[2], C=[3]}

编辑:如果您想要更通用的版本,正如 @Mr.Polywhirl 所建议的,您可以使用:

public static final <T, U> Map<U, List<T>> invertMap(Map<T, U> map) {
    HashMap<U, List<T>> invertedMap = new HashMap<>();

    for (T key : map.keySet()) {
        U newKey = map.get(key);

        invertedMap.computeIfAbsent(newKey, k -> new ArrayList<>());
        invertedMap.get(newKey).add(key);

    }

    return invertedMap;
}

【讨论】:

  • 这个问题(与您发布的原始版本相反)是每个索引需要 2 次哈希查找。如果您的哈希像示例中那样微不足道,那就没什么大不了的。如果其中有数百个项目,则应该以另一种方式进行以加快速度-此处不应超过 1 个(computeIfAbsent 必须执行 get 以查看该项目是否存在)。
  • @GabeSechan,请随时编辑我的答案以提高此代码的效率。我对 Java 了解不多。
  • 这是上面代码的通用版本。随时将其添加到您的回复中。 pastebin.com/yTExx5Fi
  • @Mr.Polywhirl,我刚刚完成了,非常感谢,这非常有用,因为它是通用的。
  • @GabeSechan Map.computeIfAbsent 返回值,无论是现有的还是新计算的,因此可以简单地写成:invertedMap.computeIfAbsent(newKey, k -&gt; new ArrayList&lt;&gt;()).add(key)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2019-08-17
  • 2012-10-20
  • 2020-10-22
  • 2012-11-30
  • 2010-09-26
  • 2020-07-20
相关资源
最近更新 更多