【问题标题】:how to avoid a nested loop如何避免嵌套循环
【发布时间】:2017-06-01 17:57:59
【问题描述】:

我正在努力实现以下目标

public class MyObject {
    Map<String, String> myMap;
}

public class MyOtherObject {
    List<MyObject> myObjects;
}

我希望能够做到以下几点

for (MyObject myObject: myObjects) {
    Map<String,String> newMap = new Hashmap<String,String>();

    for (Map.Entry<String, String> entry : myObject.getMyMap.entrySet() {
        newMap.put(entry.key + "a" , entry.value)
    }
}

如何避免这种嵌套循环?

【问题讨论】:

  • 你是在 java8 环境中运行的吗????
  • 没有 java 7,但我会对 java 8 的解决方案感到好奇
  • 顺便说一句,将 Map&lt;String,String&gt; newMap = new Hashmap&lt;String,String&gt;(); 移到 for 循环之外。您每次都在创建新地图!
  • 你无法避免嵌套循环。无论您如何实现这一点,都必须触摸每个地图中的每个键,因此您无法降低复杂性。但是,如果您只是讨厌嵌套,则可以将嵌套循环移动到私有实用程序函数中。您唯一的其他选择是编写 MyOtherObject 代码以在插入时进行转换,这样您就不必首先更改键。
  • 不清楚是要为列表的每个对象创建一个新映射,还是要一个包含内部映射的所有条目并修改其键的单个映射

标签: java data-structures hashmap nested-loops


【解决方案1】:
  • 关于您当前的解决方案,您需要将newMap 在循环之外声明,否则您将在循环的每次迭代中创建一个新映射,并且不会包含您期望的结果。
  • 您的地图实例化也有错字,请将Hashmap 更改为 HashMap

至于避免嵌套循环,您可以创建entrySet 的流实例,然后简单地使用collect 对流执行归约操作。

Map<String, String> copy = myObject.getMyMap.entrySet()
            .stream()
            .collect(Collectors.toMap(p -> p.getKey() + "a", Map.Entry::getValue));

如果您想将指定地图中的所有映射复制到另一个地图,那么正如 svasa 在 cmets 中所建议的,您可以这样做:

newMap.putAll(myObject.getMyMap.entrySet().stream().collect(Collectors.toMap(p -> p.getKey() + "a", Map.Entry::getValue)));

【讨论】:

  • 如果你能解释它是如何工作的,以及如何像newMap.putAll( myObject.getMyMap.entrySet() .stream() .collect(Collectors.toMap(p -&gt; p.getKey() + "a", Map.Entry::getValue))); 一样填充newMap 另一个注意事项是用户还需要移动上面的Map&lt;String,String&gt; newMap = new Hashmap&lt;String,String&gt;();循环。
【解决方案2】:

使用putAll:

Amap.putAll(Bmap);

【讨论】:

  • 不错,但我想在放入地图之前修改密钥
【解决方案3】:

复杂度总是O(n x m)n 是列表的大小,m 是内部映射的最大大小。

使用 java 8,您可以使用:

Map<String, String> result = myObjects.stream()
    .flatMap(myObject -> myObject.getMyMap().entrySet().stream())
    .collect(Collectors.toMap(e -> e.getKey() + "a", Entry::getValue));

这假设您只需要一个包含所有内部映射的所有条目的映射,并且它们的键已修改。

我使用flatMap 将所有带有内部映射条目的流扁平化为一个流。然后,我使用Collectors.toMap 将所有这些条目收集到一个新地图中。

如果有重复的键,这将失败。在这种情况下,您可以使用overloaded version of Collectors.toMap,它接受一个函数来在键之间发生冲突时合并值:

Map<String, String> result = myObjects.stream()
    .flatMap(myObject -> myObject.getMyMap().entrySet().stream())
    .collect(Collectors.toMap(e -> e.getKey() + "a", Entry::getValue, String::concat));

这只是将多次映射到同一个键的值连接起来,但您可以使用任何其他合并函数。

【讨论】:

  • 这有什么复杂的
猜你喜欢
  • 1970-01-01
  • 2012-06-25
  • 2017-08-27
  • 2017-11-11
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多