It sounds like you have a set of DAGs (directed acyclic graphs). I think you'll need to model this and then do a topological sort on each one. One approach:
Wrap each element in a wrapper object that references the object and has a list for holding dependencies to other objects. Put all these wrappers in a hashMap keyed by object id.
For all elements with no direct dependencies, emit the element, and remove it from the hashMap. Repeat until hashmap is empty.
If dependency lists are often long, this will be inefficient. It's intended for an average number of direct dependencies under 5 or so. If performance is a problem because too many "Repeat until hashmap is empty" passes are being made, a bidirectional data structure for representing the dependency graphs should be used, or maybe, a list of the map entries that have only one dependency on this pass, and thus are strong candidates for the next pass.
Here's an untested sketch:
class Obj { String id; }
class ObjWrapper {
String id;
Obj obj;
String[] depends; // may be null, may have null entries
public ObjWrapper(Obj obj, String[] depends) {
this.id = obj.id;
this.obj = obj;
if ( depends != null )
this.depends = Arrays.copyOf(depends, depends.length);
}
}
// order the objects by dependency.
ArrayList<Obj> orderObjs(Iterable<ObjWrapper> objs)
{
ArrayList<Obj> output = new ArrayList();
HashMap<String, ObjWrapper> objMap = new HashMap();
for ( ObjWrapper obj : objs )
objMap.put(obj.id, obj);
while ( !objMap.isEmpty() ) {
Iterator<ObjWrapper> iter = objMap.values().iterator();
while ( iter.hasNext() ) {
ObjWrapper objWrapper = iter.next();
if ( !hasDependencies(objWrapper, objMap) ) {
output.add(objWrapper.obj);
// must use iter to remove from hash, or bad things happen.
iter.remove();
}
}
}
return output;
}
boolean hasDependencies(ObjWrapper objWrapper,
HashMap<String, ObjWrapper> objMap)
{
if ( objWrapper.depends == null ) return false;
for ( String depend : objWrapper.depends ) {
if ( depend != null )
if ( objMap.containsKey(depend) )
return true;
else
depend = null; // to speed up future passes
}
return false;
}