Java multikey map with no value

204 views Asked by At

I would like to be able to query on each key with no value. A1...n , B1...n are Strings. I have Sets of Strings which I need to add into structure in order to be able to query on each String and get its group Strings.

For example : {A1, A2, A3} , {B1,B2,B3, B4....., Bn}

map.get(A1) --> return {A2,A3}
map.get(A2) --> return {A1,A3}
map.get(A3) --> return {A1,A2}
map.get(B1) --> return {B2,B3, B4...Bn}
map.get(B2) --> return {B1,B3, B4 ..Bn}
map.get(B3) --> return {B1,B2, B4...Bn}

etc...

Any recommendations which data structure should I use?

1

There are 1 answers

0
rzwitserloot On

I suggest you make a map that maps an individual key to its entire group.

So, instead of what you wrote, this:

A1 -> {A1, A2, A3}

If you then have an operation such as 'list members of the group, but dont list yourself', just write that logic at that point (loop through the group and skip over yourself / use a stream().filter() operation to do this).

This way you save a ton of memory - each 'group' can simply be the same object. This also means that if you have mutable groups, you can just operate on the group (though, you'd have to take good care to update the map in tandem):

String[][] input = {
   {"A1", "A2", "A3"},
   {"B1", "B2"}};

public Map<String, SortedSet<String>> makeGroupsData() {
    var out = new HashMap<String, List<String>>();
    for (String[] group : input) {
        SortedSet<String> groupSet = new TreeSet<>(Arrays.asList(group));
        for (String g : group) out.put(g, groupSet);
    }

    return out;
}

// and then for operations:

/** Returns a list of all <em>other</em> members of the group */
public SortedSet<String> getGroupMembers(String key) {
    var group = groups.get(key);
    if (group == null) throw new IllegalArgumentException("unknown: " + key);
    var out = new TreeSet<String>(group);
    out.remove(key);
    return out;
}

public int getGroupSize(String key) {
    Set<String> group = groups.get(key);
    return group == null ? 0 : group.size();
}

You get the drift - I'm not sure if SortedSet is right for you here, for example. The point is, this means there is only 1 object (one TreeSet) for one group, and the map just links each individual member to the same one group object.

NB: Big caveat: This assumes any given string cannot be a member of more than one group, and this code does not check for it. You may want to (the .put method returns the previous mapping, so all you have to do is check if the .put method returns a non-null value; if it does, throw an IllegalArgumentException).