如何按插入顺序迭代Multimap?

时间:2012-03-18 06:03:44

标签: java guava

使用来自Google的番石榴的新馆藏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 个答案:

答案 0 :(得分: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

但缺点是你必须为你创建三个列表,这使得这个解决方案变得相当不灵活。所以也许将{first,second,third}值集合放到Map&gt;会更好,这让我想到了这一点:


也许您应该使用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]

我故意将String用于行键[1,2,3,...]实际上是整数(就像你在问题中所做的那样)和整数用于以0开头的列键([0,1,2, ...])使用List的get(int)在多地图值集合上显示与上一个示例的相似性。

希望这会有所帮助,主要是确定你想要的东西;)

P.S。我在这里使用ArrayTable,因为它有更简洁的方法来创建行/键值的固定集(Universe)而不是ImmutableTable,但如果不需要可变性,则应该使用它而只需更改一次 - { {1}}(以及任何其他Table实现)没有ImmutableTable方法,但只有columnKeyList()执行相同的操作,但columnKeySet()的速度较慢。当然,应该使用ImmutableTable.BuilderArrayTable

答案 1 :(得分:5)

您可以使用LinkedListMultimapLinkedHashMultimap

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

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

答案 2 :(得分: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

答案 3 :(得分:2)

用于循环多个键:

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

您还可以遍历条目:

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