5555import org .hibernate .event .spi .PostLoadEventListener ;
5656import org .hibernate .internal .CoreMessageLogger ;
5757import org .hibernate .internal .util .collections .CollectionHelper ;
58- import org .hibernate .internal .util .collections .IdentityMap ;
58+ import org .hibernate .internal .util .collections .InstanceIdentityMap ;
59+ import org .hibernate .internal .util .collections .StandardStack ;
5960import org .hibernate .metamodel .spi .MappingMetamodelImplementor ;
6061import org .hibernate .persister .collection .CollectionPersister ;
6162import org .hibernate .persister .entity .EntityPersister ;
@@ -131,7 +132,11 @@ the following fields are used in all circumstances, and are not worth (or not su
131132 private IdentityHashMap <Object , PersistentCollection <?>> arrayHolders ;
132133
133134 // Identity map of CollectionEntry instances, by the collection wrapper
134- private IdentityMap <PersistentCollection <?>, CollectionEntry > collectionEntries ;
135+ private InstanceIdentityMap <PersistentCollection <?>, CollectionEntry > collectionEntries ;
136+
137+ // current collection instance id and stack of reusable ones
138+ private StandardStack <Integer > reusableCollectionInstanceIds = null ;
139+ private int currentCollectionInstanceId ;
135140
136141 // Collection wrappers, by the CollectionKey
137142 private HashMap <CollectionKey , PersistentCollection <?>> collectionsByKey ;
@@ -255,7 +260,7 @@ public void clear() {
255260
256261 final SharedSessionContractImplementor session = getSession ();
257262 if ( collectionEntries != null ) {
258- IdentityMap . onEachKey ( collectionEntries , k -> k .unsetSession ( session ) );
263+ collectionEntries . forEach ( ( k , v ) -> k .unsetSession ( session ) );
259264 }
260265
261266 arrayHolders = null ;
@@ -267,6 +272,8 @@ public void clear() {
267272 collectionsByKey = null ;
268273 nonlazyCollections = null ;
269274 collectionEntries = null ;
275+ currentCollectionInstanceId = 0 ;
276+ reusableCollectionInstanceIds = null ;
270277 unownedCollections = null ;
271278 nullifiableEntityKeys = null ;
272279 deletedUnloadedEntityKeys = null ;
@@ -1082,7 +1089,6 @@ public void replaceCollection(CollectionPersister persister, PersistentCollectio
10821089 "Replacement of not directly accessible collection found: " + oldCollection .getRole () );
10831090 }
10841091 assert !collection .isDirectlyAccessible ();
1085- final IdentityMap <PersistentCollection <?>, CollectionEntry > collectionEntries = getOrInitializeCollectionEntries ();
10861092 final CollectionEntry oldEntry = collectionEntries .remove ( oldCollection );
10871093 final CollectionEntry entry ;
10881094 if ( oldEntry .getLoadedPersister () != null ) {
@@ -1093,7 +1099,7 @@ public void replaceCollection(CollectionPersister persister, PersistentCollectio
10931099 // A newly wrapped collection
10941100 entry = new CollectionEntry ( persister , collection );
10951101 }
1096- collectionEntries . put ( collection , entry );
1102+ putCollectionEntry ( collection , entry );
10971103 final Object key = collection .getKey ();
10981104 if ( key != null ) {
10991105 final CollectionKey collectionKey = new CollectionKey ( entry .getLoadedPersister (), key );
@@ -1112,7 +1118,7 @@ public void replaceCollection(CollectionPersister persister, PersistentCollectio
11121118 * @param key The key of the collection's entry.
11131119 */
11141120 private void addCollection (PersistentCollection <?> coll , CollectionEntry entry , Object key ) {
1115- getOrInitializeCollectionEntries (). put ( coll , entry );
1121+ putCollectionEntry ( coll , entry );
11161122 final CollectionKey collectionKey = new CollectionKey ( entry .getLoadedPersister (), key );
11171123 final PersistentCollection <?> old = addCollectionByKey ( collectionKey , coll );
11181124 if ( old != null ) {
@@ -1125,11 +1131,12 @@ private void addCollection(PersistentCollection<?> coll, CollectionEntry entry,
11251131 }
11261132 }
11271133
1128- private IdentityMap < PersistentCollection <?>, CollectionEntry > getOrInitializeCollectionEntries ( ) {
1134+ private void putCollectionEntry ( PersistentCollection <?> collection , CollectionEntry entry ) {
11291135 if ( this .collectionEntries == null ) {
1130- this .collectionEntries = IdentityMap . instantiateSequenced ( INIT_COLL_SIZE );
1136+ this .collectionEntries = new InstanceIdentityMap <>( );
11311137 }
1132- return this .collectionEntries ;
1138+ collection .$$_hibernate_setInstanceId ( nextCollectionInstanceId () );
1139+ this .collectionEntries .put ( collection , entry );
11331140 }
11341141
11351142 /**
@@ -1140,7 +1147,7 @@ private IdentityMap<PersistentCollection<?>, CollectionEntry> getOrInitializeCol
11401147 */
11411148 private void addCollection (PersistentCollection <?> collection , CollectionPersister persister ) {
11421149 final CollectionEntry ce = new CollectionEntry ( persister , collection );
1143- getOrInitializeCollectionEntries (). put ( collection , ce );
1150+ putCollectionEntry ( collection , ce );
11441151 }
11451152
11461153 @ Override
@@ -1375,11 +1382,17 @@ public int getNumberOfManagedEntities() {
13751382 return collectionEntries ;
13761383 }
13771384
1385+ private int nextCollectionInstanceId () {
1386+ return reusableCollectionInstanceIds != null && !reusableCollectionInstanceIds .isEmpty () ?
1387+ reusableCollectionInstanceIds .pop () :
1388+ currentCollectionInstanceId ++;
1389+ }
1390+
13781391 @ Override
13791392 public void forEachCollectionEntry (BiConsumer <PersistentCollection <?>, CollectionEntry > action , boolean concurrent ) {
13801393 if ( collectionEntries != null ) {
13811394 if ( concurrent ) {
1382- for ( Entry <PersistentCollection <?>,CollectionEntry > entry : IdentityMap . concurrentEntries ( collectionEntries ) ) {
1395+ for ( Entry <PersistentCollection <?>,CollectionEntry > entry : collectionEntries . toArray ( ) ) {
13831396 action .accept ( entry .getKey (), entry .getValue () );
13841397 }
13851398 }
@@ -2032,7 +2045,7 @@ public static StatefulPersistenceContext deserialize(
20322045 final PersistentCollection <?> pc = (PersistentCollection <?>) ois .readObject ();
20332046 final CollectionEntry ce = CollectionEntry .deserialize ( ois , session );
20342047 pc .setCurrentSession ( session );
2035- rtn .getOrInitializeCollectionEntries (). put ( pc , ce );
2048+ rtn .putCollectionEntry ( pc , ce );
20362049 }
20372050
20382051 count = ois .readInt ();
@@ -2174,7 +2187,17 @@ public int getCollectionEntriesSize() {
21742187
21752188 @ Override
21762189 public CollectionEntry removeCollectionEntry (PersistentCollection <?> collection ) {
2177- return collectionEntries == null ? null : collectionEntries .remove (collection );
2190+ if ( collectionEntries != null ) {
2191+ final int instanceId = collection .$$_hibernate_getInstanceId ();
2192+ if ( reusableCollectionInstanceIds == null ) {
2193+ reusableCollectionInstanceIds = new StandardStack <>();
2194+ }
2195+ reusableCollectionInstanceIds .push ( instanceId );
2196+ return collectionEntries .remove ( collection );
2197+ }
2198+ else {
2199+ return null ;
2200+ }
21782201 }
21792202
21802203 @ Override
0 commit comments