The issue: Conserve a bidirectional many-to-one relationship among java objects.

Something similar to the Google/Commons Collections bidi maps, but I wish to allow duplicate values around the forward side, and also have sets from the forward secrets because the reverse side values. Used something similar to this:

// maintaining disjoint areas on a gameboard. Location is a space on the
// gameboard; Regions refer to disjoint collections of Locations.

MagicalManyToOneMap<Location, Region> forward = // the game universe
Map<Region, <Set<Location>>> inverse = forward.getInverse(); // live, not a copy
Location parkplace = Game.chooseSomeLocation(...);
Region mine = forward.get(parkplace); // assume !null; should be O(log n)
Region other = Game.getSomeOtherRegion(...);
// moving a Location from one Region to another:
forward.put(parkplace, other);
// or equivalently:
inverse.get(other).add(parkplace); // should also be O(log n) or so
// expected consistency:
assert ! inverse.get(mine).contains(parkplace);
assert forward.get(parkplace) == other;
// and this should be fast, not iterate every possible location just to filter for mine:
for (Location l : mine) { /* do something clever */ }

The easy java approaches are: 1. To keep only one for reds from the relationship, either like a Map<Location, Region> or perhaps a Map<Region, Set<Location>>, and collect the inverse relationship by iteration if needed Or, 2. To create a wrapper that keeps both sides' Maps, and intercept all mutating calls to help keep each side synchronized.

1 is O(n) rather than O(log n), that is being a problem. I began in on 2 and is at the weeds straightaway. (Know the number of various ways you will find to change a roadmap entry?)

This really is almost trivial within the sql world (Location table will get an indexed RegionID column). Can there be something apparent I am missing that causes it to be trivial for normal objects?

I would get me wrong your model, but when where you are and Region have correct equals() and hashCode() implemented, then your group of Location -> Region is simply a classical simple Map implementation (multiple distinct secrets can indicate exactly the same object value). The Location -> Group of Location is really a Multimap (obtainable in Google Coll.). You can compose your personal class using the proper add/remove techniques to control both submaps.

Maybe an overkill, but you might use within-memory sql server (HSQLDB, etc). It enables you to definitely create index on many posts.