Search code examples
javaarraylistguavamultimap

How to get the value in a nested `ArrayListMultimap`


I have the following code for a nested ArrayListMultimap:

    Multimap<String, Multimap<Integer, String>> doubleMultiMap = ArrayListMultimap.create();
    Multimap<Integer, String> doc = ArrayListMultimap.create();
    doc.put(1, "ABC");
    doc.put(2, "BCD");
    doc.put(1, "XYZ");
    doubleMultiMap.put("D123", doc);

    doc = ArrayListMultimap.create();
    doc.put(1, "John");
    doc.put(2, "Jane");
    doc.put(2, "George");
    doubleMultiMap.put("J123", doc);
    System.out.println(doubleMultiMap.get("D123")); 

For doubleMultiMap.get("D123") I get the result as [{1=[ABC, XYZ], 2=[BCD]}]

But how to get the value for keys D123, 1. I tried to use (doubleMultiMap.get("D123")).get(1) but it is not supported.

Update: What I'm trying to achieve is something like below. If nested Multimap is not ideal, what alternative could I use?

enter image description here


Solution

  • If you don't need Table-specific methods like row or column access (and it seems you don't, since you want to access D123, 1), compound key for Multimap is the solution. Create simple class storing string and integer with proper hashCode and equals and use multimap normally. Assuming your compound key class name is Key (you should think of better one) you should be able to do something like this:

    //given
    ListMultimap<Key, String> multimap = ArrayListMultimap.create(); // note ListMultimap
    multimap.put(new Key("D123", 1), "ABC");
    multimap.put(new Key("D123", 2), "BCD");
    multimap.put(new Key("D123", 1), "XYZ");
    multimap.put(new Key("J123", 1), "John");
    multimap.put(new Key("J123", 2), "Jane");
    multimap.put(new Key("J123", 2), "George");
    //when
    List<String> values = multimap.get(new Key("D123", 1));
    //then
    assertThat(values).containsExactly("ABC", "XYZ");
    

    If you need to access by row or by column (ex. get complete mapping of column 2 which in your case would have keys "D123" and "J123"), then you may want to settle with Table<String, Integer, List<String>> and take care of creating lists in table values on demand (sadly, there's no computeIfAbsent in Table interface).

    Third option would be to discuss Multitable in this Guava issue, as mentioned by @SeanPatrickFloyd in the comment above.