Search code examples
javaguavamultimap

Mapping with an AND (&&) relationship in Java


I was reading about MultiMap in Guava. It says the following relationships can be mapped:

  • a → 1, 2
  • b → 3

Is it possible to map the following relationships using a map structure in Java/Guava using just POJO?

  • a → 1, 2
  • b → 3
  • c → 3
  • d → 4
  • c && d → 5
  • f → 5

It is the second to last relationship that I am particularly interested in. c alone would give 3. d alone would give 4. c and d together would in this case return 3, 4 and 5.

How could this be achieved?

UPDATE: Ideally, I would like in the example I gave searching with a, c and d to give the result 1, 2, 3, 4 and 5. The intention would be for the mapping to be scalable to hundreds of keys, hundreds of values and hundreds of these AND relationships.

I would be expecting to use a Set to search and the result being a Set.


Solution

  • You can make the key some value type which takes a list of symbols, e.g. new AndKey('c'), new AndKey('c', 'd'), representing c and c && d respectively, and then insert values into the multimap for those keys:

    ImmutableMultimap<AndKey, Integer> map = ImmutableMultimap.builder()
        .put(new AndKey('c'), 3)
        .put(new AndKey('d'), 4)
        .put(new AndKey('c', 'd'), 3)
        .put(new AndKey('c', 'd'), 4)
        .put(new AndKey('c', 'd'), 5)
        .build();
    

    This assumes that you implement equals and hashCode appropriately in AndKey so that two instances with the same symbols are considered equal, e.g.

    class AndKey {
      private final ImmutableList<Character> symbols;
    
      AndKey(Character... symbols) { this.symbols = ImmutableList.copyOf(symbols); }
    
      @Override int hashCode() { return symbols.hashCode(); }
      @Override boolean equals(Object obj) {
        if (obj == this) { return true; }
        if (obj instanceof AndKey) { return symbols.equals(((AndKey) obj).symbols); }
        return false;
    }
    

    or use AutoValue, of course.