递归或迭代地从 HashMap 中检索键值组合
Posted
技术标签:
【中文标题】递归或迭代地从 HashMap 中检索键值组合【英文标题】:Recursively or iteratively retrieve key-value combinations from a HashMap 【发布时间】:2011-07-16 10:17:23 【问题描述】:我想从HashMap
中检索k
,v
-pairs。
条目是这样的:
a = 3,4
b = 5,6
等等。我需要这些值的组合。
a=3, b=5
a=3, b=6
a=4, b=5
a=4, b=6
我不知道值有多少个键和多少个条目。使用entrySet
我可以获得值但不能获得组合。它看起来像递归,但如何?
这是我的代码:
HashMap<String, String[]> map = new HashMap<String, String[]>();
BufferedReader file = new BufferedReader(new FileReader("test.txt"));
String str;
while ((str = file.readLine()) != null)
// ... logic
map.put(key, value);
System.out.println("number of keys: " + map.size());
for (Map.Entry<String, String[]> entry : map.entrySet())
for (String value : entry.getValue())
System.out.println(entry.getKey() + ": " + value);
file.close();
【问题讨论】:
我不清楚:“a”是您的键,“3”(来自 a 的列表)是您的值,还是“3”是 a 的键和“5”是 b 的值? a 是键,3 和 4 是字符串。因此“字符串 []”。值为 String[] 【参考方案1】:你可以试试下面的代码:
public void mapPermute(Map<String, String[]> map, String currentPermutation)
String key = map.keySet().iterator().next(); // get the topmost key
// base case
if (map.size() == 1)
for (String value : map.get(key))
System.out.println(currentPermutation + key + "=" + value);
else
// recursive case
Map<String, String[]> subMap = new HashMap<String, String[]>(map);
for (String value : subMap.remove(key))
mapPermute(subMap, currentPermutation + key + "=" + value + ", ");
不保证内存效率或速度。如果要保留映射中键的顺序,则必须传入 TreeMap
并更改代码以在递归情况下使用 TreeMap
。
正如基本情况所暗示的,我假设您的地图中至少有一个条目。
【讨论】:
【参考方案2】:您可以使用 map 和 reduce 方法获得地图键值组合的 笛卡尔积。
Try it online!
Map<String, String[]> map = Map.of(
"a", new String[]"3", "4",
"b", new String[]"5", "6");
List<Map<String, String>> comb = map.entrySet().stream()
// Stream<List<Map<String,String>>>
.map(e -> Arrays.stream(e.getValue())
.map(v -> Map.of(e.getKey(), v))
.collect(Collectors.toList()))
// summation of pairs of list into a single list
.reduce((list1, list2) -> list1.stream()
// combinations of inner maps
.flatMap(map1 -> list2.stream()
// concatenate into a single map
.map(map2 ->
Map<String, String> m = new HashMap<>();
m.putAll(map1);
m.putAll(map2);
return m;
))
// list of combinations
.collect(Collectors.toList()))
// otherwise, an empty list
.orElse(Collections.emptyList());
// output, order may vary
comb.forEach(System.out::println);
输出,顺序可能不同:
a=3, b=5
a=3, b=6
a=4, b=5
a=4, b=6
另见:Cartesian product of map values
【讨论】:
【参考方案3】:在我看来你真的想要MultiMap
。特别是,ArrayListMultimap
允许重复条目:
ArrayListMultimap<String, String> map = ArrayListMultimap.create();
for each line in file:
parse key k
for each value in line:
parse value v
map.put(k, v);
for (Map.Entry<String, String> entry : map.entries())
String key = entry.getKey();
String value = entry.getValue();
如果您想要地图的笛卡尔积,您可以直接使用递归计算,或者您可以迭代地图:创建一个迭代器列表并迭代里程表样式;当迭代器 N 到达终点时,推进迭代器 N+1 并重置迭代器 1..N。
随便找了找this SO question。
因此,我建议您使用 guava 的 Sets.cartesianProduct
作为笛卡尔积。这是我的代码,你可以适应你的输入逻辑:
String key1 = "a";
Set<Integer> values1 = Sets.newLinkedHashSet(Arrays.asList(1, 2, 3, 4));
String key2 = "b";
Set<Integer> values2 = Sets.newLinkedHashSet(Arrays.asList(5, 6, 7));
String key3 = "c";
Set<Integer> values3 = Sets.newLinkedHashSet(Arrays.asList(8, 9));
List<String> keys = Arrays.asList(key1, key2, key3);
Set<List<Integer>> product = Sets.cartesianProduct(values1, values2, values3);
for (List<Integer> values : product)
for (int i = 0; i < keys.size(); ++i)
String key = keys.get(i);
int value = values.get(i);
System.out.print(key + "=" + value + "; ");
System.out.println();
【讨论】:
AHashMultimap
将防止重复条目。但我仍然不清楚你的目标。
好的。我得到一个文本输入。这进入地图。关键是一个。这些值存储在 String[] 中。我稍后需要将这些值作为单独的字符串。所以这就是为什么它是 String[] 而不仅仅是字符串。我需要键值对中的每个组合,就像我的第一篇文章中一样。
在这种情况下,您只需要检查键值对是否已经存在于地图中。
我想我刚刚知道你想要地图的产品——就像***.com/questions/714108/…
好吧,更像是这样:***.com/questions/710670/…您的链接中给出的方法...如何将其应用于我的案例?对不起,我不是一个真正优秀的程序员......以上是关于递归或迭代地从 HashMap 中检索键值组合的主要内容,如果未能解决你的问题,请参考以下文章