@@ -43,7 +43,7 @@ public class BeanPropertyMap
43
43
* Number of entries stored in the hash area.
44
44
*/
45
45
private int _size ;
46
-
46
+
47
47
private int _spillCount ;
48
48
49
49
/**
@@ -55,7 +55,7 @@ public class BeanPropertyMap
55
55
* Array of properties in the exact order they were handed in. This is
56
56
* used by as-array serialization, deserialization.
57
57
*/
58
- private SettableBeanProperty [] _propsInOrder ;
58
+ private final SettableBeanProperty [] _propsInOrder ;
59
59
60
60
/**
61
61
* Configuration of alias mappings, indexed by unmodified property name
@@ -75,7 +75,7 @@ public class BeanPropertyMap
75
75
* @since 2.9
76
76
*/
77
77
private final Map <String ,String > _aliasMapping ;
78
-
78
+
79
79
/**
80
80
* @since 2.9
81
81
*/
@@ -89,6 +89,70 @@ public BeanPropertyMap(boolean caseInsensitive, Collection<SettableBeanProperty>
89
89
init (props );
90
90
}
91
91
92
+ /* Copy constructors used when a property can replace existing one
93
+ *
94
+ * @since 2.9.6
95
+ */
96
+ private BeanPropertyMap (BeanPropertyMap src ,
97
+ SettableBeanProperty newProp , int hashIndex , int orderedIndex )
98
+ {
99
+ // First, copy most fields as is:
100
+ _caseInsensitive = src ._caseInsensitive ;
101
+ _hashMask = src ._hashMask ;
102
+ _size = src ._size ;
103
+ _spillCount = src ._spillCount ;
104
+ _aliasDefs = src ._aliasDefs ;
105
+ _aliasMapping = src ._aliasMapping ;
106
+
107
+ // but then make deep copy of arrays to modify
108
+ _hashArea = Arrays .copyOf (src ._hashArea , src ._hashArea .length );
109
+ _propsInOrder = Arrays .copyOf (src ._propsInOrder , src ._propsInOrder .length );
110
+ _hashArea [hashIndex ] = newProp ;
111
+ _propsInOrder [orderedIndex ] = newProp ;
112
+ }
113
+
114
+ /* Copy constructors used when a property needs to be appended (can't replace)
115
+ *
116
+ * @since 2.9.6
117
+ */
118
+ private BeanPropertyMap (BeanPropertyMap src ,
119
+ SettableBeanProperty newProp , String key , int slot )
120
+ {
121
+ // First, copy most fields as is:
122
+ _caseInsensitive = src ._caseInsensitive ;
123
+ _hashMask = src ._hashMask ;
124
+ _size = src ._size ;
125
+ _spillCount = src ._spillCount ;
126
+ _aliasDefs = src ._aliasDefs ;
127
+ _aliasMapping = src ._aliasMapping ;
128
+
129
+ // but then make deep copy of arrays to modify
130
+ _hashArea = Arrays .copyOf (src ._hashArea , src ._hashArea .length );
131
+ int last = src ._propsInOrder .length ;
132
+ // and append property at the end of ordering
133
+ _propsInOrder = Arrays .copyOf (src ._propsInOrder , last +1 );
134
+ _propsInOrder [last ] = newProp ;
135
+
136
+ final int hashSize = _hashMask +1 ;
137
+ int ix = (slot <<1 );
138
+
139
+ // primary slot not free?
140
+ if (_hashArea [ix ] != null ) {
141
+ // secondary?
142
+ ix = (hashSize + (slot >> 1 )) << 1 ;
143
+ if (_hashArea [ix ] != null ) {
144
+ // ok, spill over.
145
+ ix = ((hashSize + (hashSize >> 1 ) ) << 1 ) + _spillCount ;
146
+ _spillCount += 2 ;
147
+ if (ix >= _hashArea .length ) {
148
+ _hashArea = Arrays .copyOf (_hashArea , _hashArea .length + 4 );
149
+ }
150
+ }
151
+ }
152
+ _hashArea [ix ] = key ;
153
+ _hashArea [ix +1 ] = newProp ;
154
+ }
155
+
92
156
@ Deprecated // since 2.8
93
157
public BeanPropertyMap (boolean caseInsensitive , Collection <SettableBeanProperty > props )
94
158
{
@@ -159,15 +223,11 @@ protected void init(Collection<SettableBeanProperty> props)
159
223
}
160
224
}
161
225
}
162
- //System.err.println(" add '"+key+" at #"+(ix>>1)+"/"+size+" (hashed at "+slot+")");
163
226
hashed [ix ] = key ;
164
227
hashed [ix +1 ] = prop ;
165
228
166
229
// and aliases
167
230
}
168
- //for (int i = 0; i < hashed.length; i += 2) {
169
- //System.err.printf("#%02d: %s\n", i>>1, (hashed[i] == null) ? "-" : hashed[i]);
170
- //}
171
231
_hashArea = hashed ;
172
232
_spillCount = spillCount ;
173
233
}
@@ -217,46 +277,13 @@ public BeanPropertyMap withProperty(SettableBeanProperty newProp)
217
277
for (int i = 1 , end = _hashArea .length ; i < end ; i += 2 ) {
218
278
SettableBeanProperty prop = (SettableBeanProperty ) _hashArea [i ];
219
279
if ((prop != null ) && prop .getName ().equals (key )) {
220
- _hashArea [i ] = newProp ;
221
- _propsInOrder [_findFromOrdered (prop )] = newProp ;
222
- return this ;
280
+ return new BeanPropertyMap (this , newProp , i , _findFromOrdered (prop ));
223
281
}
224
282
}
225
283
// If not, append
226
284
final int slot = _hashCode (key );
227
- final int hashSize = _hashMask +1 ;
228
- int ix = (slot <<1 );
229
-
230
- // primary slot not free?
231
- if (_hashArea [ix ] != null ) {
232
- // secondary?
233
- ix = (hashSize + (slot >> 1 )) << 1 ;
234
- if (_hashArea [ix ] != null ) {
235
- // ok, spill over.
236
- ix = ((hashSize + (hashSize >> 1 ) ) << 1 ) + _spillCount ;
237
- _spillCount += 2 ;
238
- if (ix >= _hashArea .length ) {
239
- _hashArea = Arrays .copyOf (_hashArea , _hashArea .length + 4 );
240
- // Uncomment for debugging only
241
- //for (int i = 0; i < _hashArea.length; i += 2) {
242
- // if (_hashArea[i] != null) {
243
- // System.err.println("Property #"+(i/2)+" '"+_hashArea[i]+"'...");
244
- // }
245
- //}
246
- //System.err.println("And new propr #"+slot+" '"+key+"'");
247
- }
248
- }
249
- }
250
- _hashArea [ix ] = key ;
251
- _hashArea [ix +1 ] = newProp ;
252
-
253
- int last = _propsInOrder .length ;
254
- _propsInOrder = Arrays .copyOf (_propsInOrder , last +1 );
255
- _propsInOrder [last ] = newProp ;
256
285
257
- // should we just create a new one? Or is resetting ok?
258
-
259
- return this ;
286
+ return new BeanPropertyMap (this , newProp , key , slot );
260
287
}
261
288
262
289
public BeanPropertyMap assignIndexes ()
0 commit comments