GraphTypeMap implements TypeMap<H> { @Override public Set<H> getAll(final Type t) { Set<H> result = new HashSet<>(1); TypeToken tt = TypeToken.of(t); MutableGraph<TypeToken> traverseGraph = Graphs.clone(typeGraph); Set<TypeToken> nodes = traverseGraph.nodes(); List<TypeToken> nodesToRemove = new ArrayList<>(); do { for (TypeToken token : nodes) { if (traverseGraph.inDegree(token) == 0) { nodesToRemove.add(token); if (tt.isSubtypeOf(token)) { result.add(handlers.get(token)); } } } for (TypeToken token : nodesToRemove) { if (!traverseGraph.removeNode(token)) { throw new IllegalStateException("Cannot remove " + token + " from " + traverseGraph); } } nodesToRemove.clear(); nodes = traverseGraph.nodes(); } while (result.isEmpty() && !nodes.isEmpty()); return result; } GraphTypeMap();  GraphTypeMap(final int expectedSize); @Override Set<H> getAll(final Type t); @Override @SuppressFBWarnings("RV_RETURN_VALUE_IGNORED") boolean putIfNotPresent(final Type type, final H appender); @Override boolean remove(final Type type); @Override String toString(); @Override H getExact(final Type t);  }
@Test public void testBehavior() { TypeMap<String> registry = new GraphTypeMap<>(); registry.safePut(Object.class, "OBJECT"); registry.safePut(GraphTypeMapTest.class, "TEST"); registry.safePut(CharSequence.class, "CHARSEQUENCE"); registry.safePut(Serializable.class, "SERIALIZABLE"); registry.safePut(Deque.class, "DEQUE"); registry.safePut(Collection.class, "COLLECTION"); Assert.assertEquals("TEST", registry.get(GraphTypeMapTest.class)); Assert.assertEquals("OBJECT", registry.get(Object.class)); try { registry.get(String.class); Assert.fail(); } catch (IllegalArgumentException ex) { } Assert.assertThat(registry.getAll(String.class), Matchers.hasItems("SERIALIZABLE", "CHARSEQUENCE")); Assert.assertEquals("SERIALIZABLE", registry.get(HostAndPort.class)); Assert.assertEquals("SERIALIZABLE", registry.get(ColumnDef.class)); Assert.assertThat(registry.getAll(ArrayDeque.class), Matchers.hasItems("SERIALIZABLE", "DEQUE")); }