2012-06-05 8 views
3

Каков наилучший способ перебора «де-нормированной» карты коллекций?Итерация по списку на карте

Для меня, например, следующую карту:

Map<String, List<String>> relations; 

Для того, чтобы перебирать каждый ключ -> значение каждого я сделать что-то вроде:

for (Entry<String,List<String>> e : relations.entries()) { 
    for (String s : e.getValue()) { 
     System.out.println(e.getKey() + " - " + s); 
    } 
} 

Есть элегантный способ решения это с каким-то декоратором или так?

Я в надежде найти что-то вроде:

for(Entry e : Collections.getDenormalizeEntriesFromMapOfCollection(myMap)) { 
    System.out.println(e.getKey() + " - " + e.getValue()); 
} 

Это даст тот же результат, только на второй ситуации вы бы одну запись для каждого ключа -> элемента коллекции.

+2

[Guava] (https://code.google.com/p/guava-libraries/) ['Multimap'] (http://docs.guava-libraries.googlecode.com/git/javadoc/com/ google/common/collect/Multimap.html) должен быть в состоянии делать то, что вы хотите (если вы можете переключиться с «Карта >»). Если вас интересуют только самые внутренние значения каждого «списка », также существует «Iterables.concat (relations.values ​​())». –

+0

еще лучше;) спасибо! –

ответ

4

Я бы порекомендовал вам взглянуть на гуавы MultiMap. Это уже есть этот вид итератора:

Чтобы преобразовать Map<K, Collection<V> к MultiMap<K, V> вы можете использовать метод полезности:

public static <K,V> Multimap<K,V> toMultiMap(Map<K,? extends Collection<V>> m) { 

    LinkedListMultimap<K, V> multimap = LinkedListMultimap.create(); 

    for (Entry<K, ? extends Collection<V>> e : m.entrySet()) 
     multimap.putAll(e.getKey(), e.getValue()); 

    return multimap; 
} 

Использование:

public static void main(String[] args) { 

    Map<String, List<Integer>> map = new HashMap<String, List<Integer>>(); 

    map.put("Hello", Arrays.asList(1, 2)); 
    map.put("World!", Arrays.asList(3)); 

    Multimap<String, Integer> multimap = toMultiMap(map); 

    Iterator<Entry<String, Integer>> it = multimap.entries().iterator(); 

    while (it.hasNext()) 
     System.out.println(it.next()); 
} 

Выходы:

Hello=1 
Hello=2 
World=3 
0

Я думаю, что отладчик Eclipse делает именно это, вы можете проверить реализацию. В противном случае вы можете написать вспомогательный метод в классе утилиты, например, поскольку структура Collections не поддерживает это, насколько я знаю.

3

Нет более элегантного способа, как тот, который вы используете для перебора по Map<String, List<String>>. Но более элегантной задачей было бы использовать Guava ListMultimap, который предоставляет метод entries(), по которому вы можете выполнять итерацию напрямую, без вложенного цикла.

Смежные вопросы