How can I iterate through a Guava multimap to print out values as pairs

user3590149 picture user3590149 · May 6, 2014 · Viewed 9.5k times · Source

For each key in a Guava Multimap I need to take the corresponding values and make pairs with them that are not dependent on order.Uniqueness of pairs are not dependent on order for make pairs inside of key. [A,B] = [B,A]. If the pair [B,A] is found in another key then this should treated as another pair. I don't know how iterate the values so I can print out pairs that aren't dependent on order. I'm not sure how to index this either. For arrays, I could just use a double loop.

Here is an example Multimap:

BE0004429: [DB00515, DB00951, DB01582]
BE0000059: [DB00603, DB01285]
BE0001052: [DB00366, DB00472, DB00856, DB01104, DB01149]

I want to take that data and change it to this format. Look carefully, I'm trying to take the values of each key and make pairs.

I want take the first value in the each key and pair it up with the other values. Take the second value and pair it with the value after. Until there no more unique pairs.

DB00515, DB00951
DB00515, DB01582
DB01582, DB00951

DB00603, DB01285

DB00366, DB00472
DB00366, DB00856
DB00366, DB01104
DB00366, DB01149
DB00472, DB00856
DB00472, DB01104
DB00472, DB01149
DB00856, DB01104
DB00856, DB01149
DB01104, DB01149

Answer

dimo414 picture dimo414 · May 6, 2014

I wrote this answer before the question was updated to more clearly describe the desired behavior, however I suspect this answer will still help some people who stumble on this question trying to understand different ways to iterate over a Multimap, so I'm leaving this answer here for posterity. See my other answer, above, for what OP was actually looking for.


Suppose we start with the following Multimap:

Multimap<String, Integer> map = new ImmutableSetMultimap.Builder<String, Integer>()
                                .put("one", 1)
                                .putAll("several", 1, 2, 3)
                                .putAll("many", 1, 2, 3, 4, 5)
                                .build();

We can print it's contents several ways, let's try them:

  1. As a raw string:

    map.toString()
    
    {one=[1], several=[1, 2, 3], many=[1, 2, 3, 4, 5]}
    
  2. As a collection of key => collection pairs, with unique keys:

    for(String key : map.keySet()) {
      System.out.println(key+": "+map.get(key));
    }
    
    // OR with the asMap() view
    
    for(Entry<String,Collection<Integer> e : map.asMap().entrySet()) {
      System.out.println(e.getKey()+": "+e.getValue());
    }
    
    one: [1]
    several: [1, 2, 3]
    many: [1, 2, 3, 4, 5]
    
  3. As a collection of key => value pairs, with duplicate keys (and possibly values, if it's a ListMultimap):

    for(Entry<String, Integer> e : map.entries()) {
      System.out.println(e.getKey()+": "+e.getValue());
    }
    
    one: 1
    several: 1
    several: 2
    several: 3
    many: 1
    many: 2
    many: 3
    many: 4
    many: 5
    
  4. As a collection of values, without concern for their keys:

    for(Integer v : map.values()) {
      System.out.println(v);
    }
    
    1
    1
    2
    3
    1
    2
    3
    4
    5
    

Those are generally the ways you'd work with a Multimap. You say you're trying to "print out pairs that aren't dependent on order" - it's unclear to me what that means, but if you're saying you want the output of option 3 to be in an arbitrary order, you could write your strings to a list, then shuffle it, like so:

List<String> pairs = new ArrayList<>();
for(Entry<String, Integer> e : map.entries()) {
  pairs.add(e.getKey()+": "+e.getValue());
}
Collections.shuffle(pairs);
for(String s : pairs) {
  System.out.println(s);
}

This would print your Multimap's contents as pairs in arbitrary order.