-import gnu.trove.map.hash.THashMap;\r
-\r
-import java.beans.PropertyChangeEvent;\r
-import java.beans.PropertyChangeListener;\r
-import java.util.Collection;\r
-import java.util.Collections;\r
-import java.util.Map;\r
-
-/**\r
- * Base class of all scene graph nodes which can have a set of sub-nodes\r
- * (children). This class only provides support for unordered children.\r
- * \r
- * @param <T>\r
- */\r
-public abstract class ParentNode<T extends INode> extends Node {\r
-\r
- private static final long serialVersionUID = 8519410262849626534L;\r
-\r
- public static final String EXISTING = "#EXISTING#";\r
- public static final String UNLINK = "#UNLINK#";\r
- public static final String NULL = "#NULL#";\r
-\r
- protected static final String[] EMPTY_STRING_ARRAY = {};\r
-\r
- @SuppressWarnings("rawtypes")\r
- private static final Map DISPOSED_CHILDREN = Collections.emptyMap();\r
-\r
- /**\r
- * A value used for {@link #rootNodeCache} to indicate the node has been\r
- * disposed and the root node cache is to be considered indefinitely\r
- * invalid.\r
- */\r
- protected static final ParentNode<?> DISPOSED = new ParentNode<INode>() {\r
- private static final long serialVersionUID = 6155494069158034123L;\r
- @Override\r
- public void asyncRemoveNode(INode node) {\r
- throw new Error();\r
- }\r
- };\r
-\r
- protected transient Map<String, T> children = createChildMap();\r
-
- /**\r
- * A cached value for the root node of this parent node. This makes it\r
- * possible to optimize {@link #getRootNode()} so that not all invocations\r
- * go through the whole node hierarchy to find the root. This helps in\r
- * making {@link ILookupService} located in the root node perform better and\r
- * therefore be more useful.\r
- * \r
- * @see #DISPOSED\r
- */\r
- protected transient volatile ParentNode<?> rootNodeCache;\r
-\r
- protected Map<String, T> createChildMap() {\r
- return new THashMap<String, T>(1);\r
- }\r
- \r
+import java.beans.PropertyChangeEvent;
+import java.beans.PropertyChangeListener;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
+
+import gnu.trove.map.TLongObjectMap;
+import gnu.trove.map.hash.TLongObjectHashMap;
+
+/**
+ * Base class of all scene graph nodes which can have a set of sub-nodes
+ * (children). This class only provides support for unordered children.
+ *
+ * @param <T>
+ */
+public abstract class ParentNode<T extends INode> extends Node {
+
+ private static final long serialVersionUID = 8519410262849626534L;
+
+ public static final String EXISTING = "#EXISTING#";
+ public static final String UNLINK = "#UNLINK#";
+ public static final String NULL = "#NULL#";
+
+ /**
+ * A value used for {@link #rootNodeCache} to indicate the node has been
+ * disposed and the root node cache is to be considered indefinitely
+ * invalid.
+ */
+ protected static final ParentNode<?> DISPOSED = new ParentNode<INode>() {
+ private static final long serialVersionUID = 6155494069158034123L;
+ @Override
+ public void asyncRemoveNode(INode node) {
+ throw new Error();
+ }
+ };
+
+ private static class ImmutableIdMap extends TLongObjectHashMap<String> {
+ private static final String MSG = "immutable singleton instance";
+
+ @Override
+ public String put(long key, String value) {
+ throw new UnsupportedOperationException(MSG);
+ }
+ @Override
+ public void putAll(Map<? extends Long, ? extends String> map) {
+ throw new UnsupportedOperationException(MSG);
+ }
+ @Override
+ public void putAll(TLongObjectMap<? extends String> map) {
+ throw new UnsupportedOperationException(MSG);
+ }
+ @Override
+ public String putIfAbsent(long key, String value) {
+ throw new UnsupportedOperationException(MSG);
+ }
+ }
+
+ /**
+ * This is the value given to {@link #children} when this node is disposed and
+ * cleaned up.
+ */
+ private static final Map<String, INode> DISPOSED_CHILDREN = Collections.emptyMap();
+
+ /**
+ * This is the value given to {@link #childrenIdMap} when this node is disposed
+ * and cleaned up.
+ */
+ private static final TLongObjectMap<String> DISPOSED_CHILDREN_ID_MAP = new ImmutableIdMap();
+
+ protected transient Map<String, INode> children = createChildMap();
+ private transient TLongObjectMap<String> childrenIdMap = new TLongObjectHashMap<>();
+
+ /**
+ * A cached value for the root node of this parent node. This makes it
+ * possible to optimize {@link #getRootNode()} so that not all invocations
+ * go through the whole node hierarchy to find the root. This helps in
+ * making {@link ILookupService} located in the root node perform better and
+ * therefore be more useful.
+ *
+ * @see #DISPOSED
+ */
+ protected transient volatile ParentNode<?> rootNodeCache;
+
+ protected Map<String, INode> createChildMap() {
+ return createChildMap(1);
+ }
+
+ protected Map<String, INode> createChildMap(int initialCapacity) {
+ // With JDK 1.8 HashMap is faster than Trove
+ return new HashMap<>(initialCapacity);
+ }
+