2012-03-18 111 views
6

使用来自谷歌的番石榴新的集合,http://code.google.com/p/guava-libraries/wiki/NewCollectionTypesExplained如何按照插入顺序遍历Multimap?

我如何遍历多重映射在插入的顺序中的每个关键?

例如

multimap = new HashMultiMap<String,String>(); 
multimap.put("1", "value1"); 
multimap.put("1", "value2"); 
multimap.put("1", "value3"); 

multimap.put("2", "value11"); 
multimap.put("2", "value22"); 
multimap.put("2", "value33"); 

multimap.put("3", "value111"); 
multimap.put("3", "value222"); 
multimap.put("3", "value333"); 

每次循环我需要

"value1", "value11", "value111"; 

那么下一个循环

"value2", "value22", "value222"; 

等:

"value3", "value33", "value333"; 
+4

'哈希*'集合不保留插入顺序。 – SLaks 2012-03-18 06:06:07

+0

看起来像我需要使用表不是一个MultiMap – KJW 2012-03-18 07:27:55

回答

11

我不太清楚你有什么需要(或具体使用情况),但我会尝试猜测。其他答案建议使用Linked * Multimap或Immutable,但要获得期望的输出结果(如有问题)使用Multimap,您将不得不创建一些花哨的Map(我将在稍后讨论)或例如创建三个临时集合,分别持有第一个,第二个和每个键的第三个值(如果使用建议的Multimap实现中的一个,它们将按照插入顺序)。最好这将是一个ListMultimaps,你可以遍历multimap.keySet()通过指数来获得与可用值列表:

final ListMultimap<String,String> multimap = LinkedListMultimap.create(); 
// put values from question here 

final List<Object> firstValues = Lists.newArrayList(); 
for (final String key: multimap.keySet()) { 
    firstValues.add(multimap.get(key).get(0)); 
}  
System.out.println(firstValues); 
// prints [value1, value11, value111] 
// similar for multimap.get(key).get(1) and so on 

但缺点是,你必须为你创建例如三个列表是什么使这个解决方案,而不易伸缩。因此,也许它会更好地把{第一,第二,第三}值集合地图>,是什么使我想到了这一点:


也许你应该使用Table呢?

表被设计为是相关联的有序对键的集合,称为行密钥和列密钥,用一个单一的价值和,更重要的是这里很重要,有行和列的意见。我在这里使用ArrayTable

final ArrayTable<String, Integer, Object> table = ArrayTable.create(
    ImmutableList.of("1", "2", "3"), ImmutableList.of(0, 1, 2)); 

table.put("1", 0, "value1"); 
table.put("1", 1, "value2"); 
table.put("1", 2, "value3"); 

table.put("2", 0, "value11"); 
table.put("2", 1, "value22"); 
table.put("2", 2, "value33"); 

table.put("3", 0, "value111"); 
table.put("3", 1, "value222"); 
table.put("3", 2, "value333"); 

for (final Integer columnKey : table.columnKeyList()) { 
    System.out.println(table.column(columnKey).values()); 
} 
// prints: 
// [value1, value11, value111] 
// [value2, value22, value222] 
// [value3, value33, value333] 

我刻意用字符串行密钥,其[1,2,3,...]实际上整数(就像你在这个问题所做的)和整数列键从0开始([0,1,2,...]),以显示与使用List的get(int)关于多图表值集合的前一个示例的相似性。

希望这将是有益的,主要是在确定你想要的东西;)

附:我在这里使用ArrayTable,因为它创建的行/键值的固定集(Universe)比ImmutableTable更好,但是如果不需要可变性,则应该使用它来代替一个更改 - ImmutableTable(以及任何其他表实现)不会没有columnKeyList()方法,但只有columnKeySet()它做同样的事情,但ArrayTable慢。当然应该使用ImmutableTable.BuilderImmutableTable.copyOf(Table)

+1

我结束了使用表,并迭代每一行,得到一个代表整个行的地图。 – KJW 2012-03-18 18:40:34

2

对于遍历多个密钥:

for (Object key : multimap.keys()) { ... } 

你也可以遍历所有的条目:

for (Map.Entry entry : multimap.entries()) { ... } 
+0

这是我困惑的地方,我在前面的问题中看到了这一点,但我不确定这是如何工作的?它是否返回特定键的所有值或返回与键相关的每个值?有没有这样的例子呢? – KJW 2012-03-18 06:09:13

4

您可以使用LinkedListMultimapLinkedHashMultimap

这两者有非常相似的行为;一个主要区别是LinkedListMultimap允许插入相同键值对的多个副本,而LinkedHashMultimap只允许一个。

有关更多信息,请参阅上面链接的Javadoc。

+0

我不确定第一点。我尝试了一个正在运行的示例,使用这两个multimaps的迭代顺序与使用键,值,条目和asMap相同。 – dawww 2014-11-19 10:26:24

+1

@dawww:哎呀,你说得对。我一定误解了文档。我会删除那个子弹点,谢谢。 :-) – ruakh 2014-11-19 16:27:31

3

我不完全清楚你的意思迭代顺序,OP ...

  • Set<K> keySet()仅返回键。
  • Map<K, Collection<V>> asMap()返回密钥及其关联条目,因此您可以使用for (Map.Entry<K, Collection<V>> entry : asMap().entrySet())来遍历密钥及其关联集合。
  • Collection<Map.Entry<K, V>> entries()可以让你迭代条目,但不一定按键对它们进行分组。

如果你想要的东西的插入顺序,使用插入排序Multimap实现之一 - LinkedHashMultimap,可能LinkedListMultimapImmutableMultimap