20
20
import io .micronaut .core .annotation .Nullable ;
21
21
import io .micronaut .core .beans .BeanIntrospection ;
22
22
import io .micronaut .core .naming .Named ;
23
+ import io .micronaut .core .util .StringIntMap ;
23
24
24
- import java .util .AbstractMap ;
25
25
import java .util .ArrayList ;
26
26
import java .util .Arrays ;
27
27
import java .util .BitSet ;
@@ -50,11 +50,7 @@ final class PropertiesBag<T> {
50
50
@ Nullable
51
51
private final Map <String , Integer > nameToPropertiesMapping ;
52
52
private final long propertiesMask ;
53
- // hash table with open addressing and linear probing that associates the key with the index
54
- // similar to JDK maps but with int values
55
- private final String [] keyTable ;
56
- private final int [] indexTable ;
57
- private final int tableMask ;
53
+ private final StringIntMap nameToPosition ;
58
54
59
55
private PropertiesBag (BeanIntrospection <T > beanIntrospection ,
60
56
int [] originalNameToPropertiesMapping ,
@@ -74,74 +70,49 @@ private PropertiesBag(BeanIntrospection<T> beanIntrospection,
74
70
propStream = Stream .concat (propStream , nameToPropertiesMapping .keySet ().stream ());
75
71
}
76
72
Set <String > props = propStream .collect (Collectors .toSet ());
77
- int tableSize = (props .size () * 2 ) + 1 ;
78
- tableSize = Integer .highestOneBit (tableSize ) * 2 ; // round to next power of two
79
- tableMask = tableSize - 1 ;
80
- this .keyTable = new String [tableSize ];
81
- this .indexTable = new int [keyTable .length ];
73
+ nameToPosition = new StringIntMap (props .size ());
82
74
for (String prop : props ) {
83
- int tableIndex = ~probe (prop );
84
- keyTable [tableIndex ] = prop ;
85
- indexTable [tableIndex ] = propertyIndexOfSlow (prop );
86
- }
87
- }
88
-
89
- private int probe (String key ) {
90
- int n = keyTable .length ;
91
- int i = key .hashCode () & tableMask ;
92
- while (true ) {
93
- String candidate = keyTable [i ];
94
- if (candidate == null ) {
95
- return ~i ;
96
- } else if (candidate .equals (key )) {
97
- return i ;
98
- } else {
99
- i ++;
100
- if (i == n ) {
101
- i = 0 ;
102
- }
103
- }
75
+ nameToPosition .put (prop , propertyIndexOfSlow (prop ));
104
76
}
105
77
}
106
78
107
79
/**
108
- * Get the properties in this bag with their property names .
80
+ * Get the properties in this bag.
109
81
*
110
82
* @return All properties in this bag
111
83
*/
112
- public List <Map . Entry < String , DeserBean .DerProperty <T , Object > >> getProperties () {
113
- Stream <AbstractMap . SimpleEntry < String , DeserBean .DerProperty <T , Object > >> originalProperties = Arrays .stream (originalNameToPropertiesMapping )
84
+ List <DeserBean .DerProperty <T , Object >> getProperties () {
85
+ Stream <DeserBean .DerProperty <T , Object >> originalProperties = Arrays .stream (originalNameToPropertiesMapping )
114
86
.filter (index -> index != -1 )
115
87
.mapToObj (index -> {
116
88
DeserBean .DerProperty <T , Object > prop = properties [index ];
117
89
if (prop .beanProperty == null ) {
118
90
return null ;
119
91
}
120
- return new AbstractMap . SimpleEntry <>( prop . beanProperty . getName (), prop ) ;
92
+ return prop ;
121
93
});
122
- Stream <AbstractMap . SimpleEntry < String , DeserBean .DerProperty <T , Object >>> mappedByName = nameToPropertiesMapping == null ? Stream .empty () : nameToPropertiesMapping .entrySet ()
94
+ Stream <DeserBean .DerProperty <T , Object >> mappedByName = nameToPropertiesMapping == null ? Stream .empty () : nameToPropertiesMapping .values ()
123
95
.stream ()
124
- .map (e -> new AbstractMap . SimpleEntry <>( e . getKey (), properties [e . getValue ()]) );
96
+ .map (index -> properties [index ] );
125
97
return Stream .concat (originalProperties , mappedByName )
126
- .collect ( Collectors . toList () );
98
+ .toList ();
127
99
}
128
100
129
101
/**
130
102
* Get the properties in this bag.
131
103
*
132
104
* @return All properties in this bag
133
105
*/
134
- public List <DeserBean .DerProperty <T , Object >> getDerProperties () {
106
+ List <DeserBean .DerProperty <T , Object >> getDerProperties () {
135
107
return Collections .unmodifiableList (Arrays .asList (properties ));
136
108
}
137
109
138
- public DeserBean .DerProperty <T , Object >[] getPropertiesArray () {
110
+ DeserBean .DerProperty <T , Object >[] getPropertiesArray () {
139
111
return properties ;
140
112
}
141
113
142
- public int propertyIndexOf (@ NonNull String name ) {
143
- int i = probe (name );
144
- return i < 0 ? -1 : indexTable [i ];
114
+ int propertyIndexOf (@ NonNull String name ) {
115
+ return nameToPosition .get (name , -1 );
145
116
}
146
117
147
118
private int propertyIndexOfSlow (@ NonNull String name ) {
@@ -156,45 +127,31 @@ private int propertyIndexOfSlow(@NonNull String name) {
156
127
return nameToPropertiesMapping == null ? -1 : nameToPropertiesMapping .getOrDefault (name , -1 );
157
128
}
158
129
159
- public Consumer newConsumer () {
130
+ Consumer newConsumer () {
160
131
return propertiesMask == 0 ? new ConsumerBig () : new ConsumerSmall ();
161
132
}
162
133
163
134
/**
164
135
* Properties consumer.
165
136
*/
166
- public abstract sealed class Consumer {
137
+ abstract sealed class Consumer {
167
138
private Consumer () {
168
139
}
169
140
170
- public boolean isNotConsumed (String name ) {
171
- int propertyIndex = propertyIndexOf (name );
172
- return propertyIndex != -1 && !isConsumed (propertyIndex );
173
- }
174
-
175
- public DeserBean .DerProperty <T , Object > findNotConsumed (String name ) {
176
- int propertyIndex = propertyIndexOf (name );
177
- if (propertyIndex == -1 || isConsumed (propertyIndex )) {
178
- return null ;
179
- }
180
- return properties [propertyIndex ];
181
- }
182
-
183
141
public DeserBean .DerProperty <T , Object > consume (String name ) {
184
- int propertyIndex = propertyIndexOf (name );
142
+ int propertyIndex = nameToPosition . get (name , - 1 );
185
143
if (propertyIndex == -1 || isConsumed (propertyIndex )) {
186
144
return null ;
187
145
}
188
146
setConsumed (propertyIndex );
189
147
return properties [propertyIndex ];
190
148
}
191
149
192
- public DeserBean . DerProperty < T , Object > consume (int propertyIndex ) {
150
+ public void consume (int propertyIndex ) {
193
151
if (propertyIndex == -1 || isConsumed (propertyIndex )) {
194
- return null ;
152
+ return ;
195
153
}
196
154
setConsumed (propertyIndex );
197
- return properties [propertyIndex ];
198
155
}
199
156
200
157
public List <DeserBean .DerProperty <T , Object >> getNotConsumed () {
@@ -255,7 +212,7 @@ public boolean isAllConsumed() {
255
212
}
256
213
}
257
214
258
- public static class Builder <T > {
215
+ static class Builder <T > {
259
216
260
217
private final BeanIntrospection <T > beanIntrospection ;
261
218
private final int [] originalNameToPropertiesMapping ;
@@ -264,19 +221,19 @@ public static class Builder<T> {
264
221
265
222
private final List <DeserBean .DerProperty <T , Object >> mutableProperties ;
266
223
267
- public Builder (BeanIntrospection <T > beanIntrospection ) {
224
+ Builder (BeanIntrospection <T > beanIntrospection ) {
268
225
this (beanIntrospection , beanIntrospection .getBeanProperties ().size ());
269
226
}
270
227
271
- public Builder (BeanIntrospection <T > beanIntrospection , int expectedPropertiesSize ) {
228
+ Builder (BeanIntrospection <T > beanIntrospection , int expectedPropertiesSize ) {
272
229
this .beanIntrospection = beanIntrospection ;
273
230
int beanPropertiesSize = beanIntrospection .getBeanProperties ().size ();
274
231
this .originalNameToPropertiesMapping = new int [beanPropertiesSize ];
275
232
Arrays .fill (originalNameToPropertiesMapping , -1 );
276
233
this .mutableProperties = new ArrayList <>(expectedPropertiesSize );
277
234
}
278
235
279
- public void register (String name , DeserBean .DerProperty <T , Object > derProperty , boolean addAliases ) {
236
+ void register (String name , DeserBean .DerProperty <T , Object > derProperty , boolean addAliases ) {
280
237
int newPropertyIndex = mutableProperties .size ();
281
238
if (derProperty .beanProperty != null && derProperty .beanProperty .getDeclaringBean () == beanIntrospection && name .equals (derProperty .beanProperty .getName ())) {
282
239
originalNameToPropertiesMapping [beanIntrospection .propertyIndexOf (name )] = newPropertyIndex ;
@@ -295,11 +252,10 @@ public void register(String name, DeserBean.DerProperty<T, Object> derProperty,
295
252
}
296
253
}
297
254
mutableProperties .add (derProperty );
298
-
299
255
}
300
256
301
257
@ Nullable
302
- public PropertiesBag <T > build () {
258
+ PropertiesBag <T > build () {
303
259
if (mutableProperties .isEmpty ()) {
304
260
return null ;
305
261
}
0 commit comments