0

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?

userit1985
  • 961
  • 1
  • 13
  • 28
  • I assume `blah.get(B1)` should also return the `B4...Bn`? – Thomas Hirsch May 03 '21 at 11:57
  • Are A1, A2 and A3 all equal? If so, how do you distinguish all three? If not, how do you decide they are a matching set? – Mureinik May 03 '21 at 12:04
  • This question is not clear. What are the types of A1 and B1? If they are different, this doesn't work from the outset (As that means `blah` has heterogenous key types, not a good start). No get call in your example returns 'no value'. – rzwitserloot May 03 '21 at 12:06
  • @rzwitserloot 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. – userit1985 May 03 '21 at 12:17
  • I don't quite understand what you are trying to do, yet. What is the relation between the Strings "A1"..."An", "B1"..."Bn" and the Sets of Strings you want to add into some structure? And this structure is yet to choose (however you called it map in your example), right? Also did you mention "Group Strings", what are these? – gkhaos May 03 '21 at 12:54

1 Answers1

0

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).

rzwitserloot
  • 85,357
  • 5
  • 51
  • 72