Skip to content

Commit d1bf594

Browse files
authored
Use StringIntMap from Core, refactoring (#772)
1 parent 14c5c0e commit d1bf594

File tree

2 files changed

+29
-79
lines changed

2 files changed

+29
-79
lines changed

serde-support/src/main/java/io/micronaut/serde/support/deserializers/DeserBean.java

+4-10
Original file line numberDiff line numberDiff line change
@@ -438,16 +438,12 @@ void initialize(Deserializer.DecoderContext decoderContext) throws SerdeExceptio
438438

439439
private void initializeInternal(Deserializer.DecoderContext decoderContext) throws SerdeException {
440440
if (injectProperties != null) {
441-
List<Map.Entry<String, DerProperty<T, Object>>> properties = injectProperties.getProperties();
442-
for (Map.Entry<String, DerProperty<T, Object>> e : properties) {
443-
DerProperty<T, Object> property = e.getValue();
441+
for (DerProperty<T, Object> property : injectProperties.getProperties()) {
444442
initProperty(property, decoderContext);
445443
}
446444
}
447445
if (creatorParams != null) {
448-
List<Map.Entry<String, DerProperty<T, Object>>> properties = creatorParams.getProperties();
449-
for (Map.Entry<String, DerProperty<T, Object>> e : properties) {
450-
DerProperty<T, Object> property = e.getValue();
446+
for (DerProperty<T, Object> property : creatorParams.getProperties()) {
451447
initProperty(property, decoderContext);
452448
}
453449
}
@@ -466,8 +462,7 @@ private boolean isSimpleBean() {
466462
return false;
467463
}
468464
if (injectProperties != null) {
469-
for (Map.Entry<String, DerProperty<T, Object>> e : injectProperties.getProperties()) {
470-
DerProperty<T, Object> property = e.getValue();
465+
for (DerProperty<T, Object> property : injectProperties.getProperties()) {
471466
if (property.isAnySetter || property.views != null || property.managedRef != null || introspection != property.instrospection || property.backRef != null || property.beanProperty == null) {
472467
return false;
473468
}
@@ -481,8 +476,7 @@ private boolean isRecordLikeBean() {
481476
return false;
482477
}
483478
if (creatorParams != null) {
484-
for (Map.Entry<String, DerProperty<T, Object>> e : creatorParams.getProperties()) {
485-
DerProperty<T, Object> property = e.getValue();
479+
for (DerProperty<T, Object> property : creatorParams.getProperties()) {
486480
if (property.beanProperty != null && !property.beanProperty.isReadOnly() || property.isAnySetter || property.views != null || property.managedRef != null || introspection != property.instrospection || property.backRef != null) {
487481
return false;
488482
}

serde-support/src/main/java/io/micronaut/serde/support/deserializers/PropertiesBag.java

+25-69
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
import io.micronaut.core.annotation.Nullable;
2121
import io.micronaut.core.beans.BeanIntrospection;
2222
import io.micronaut.core.naming.Named;
23+
import io.micronaut.core.util.StringIntMap;
2324

24-
import java.util.AbstractMap;
2525
import java.util.ArrayList;
2626
import java.util.Arrays;
2727
import java.util.BitSet;
@@ -50,11 +50,7 @@ final class PropertiesBag<T> {
5050
@Nullable
5151
private final Map<String, Integer> nameToPropertiesMapping;
5252
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;
5854

5955
private PropertiesBag(BeanIntrospection<T> beanIntrospection,
6056
int[] originalNameToPropertiesMapping,
@@ -74,74 +70,49 @@ private PropertiesBag(BeanIntrospection<T> beanIntrospection,
7470
propStream = Stream.concat(propStream, nameToPropertiesMapping.keySet().stream());
7571
}
7672
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());
8274
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));
10476
}
10577
}
10678

10779
/**
108-
* Get the properties in this bag with their property names.
80+
* Get the properties in this bag.
10981
*
11082
* @return All properties in this bag
11183
*/
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)
11486
.filter(index -> index != -1)
11587
.mapToObj(index -> {
11688
DeserBean.DerProperty<T, Object> prop = properties[index];
11789
if (prop.beanProperty == null) {
11890
return null;
11991
}
120-
return new AbstractMap.SimpleEntry<>(prop.beanProperty.getName(), prop);
92+
return prop;
12193
});
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()
12395
.stream()
124-
.map(e -> new AbstractMap.SimpleEntry<>(e.getKey(), properties[e.getValue()]));
96+
.map(index -> properties[index]);
12597
return Stream.concat(originalProperties, mappedByName)
126-
.collect(Collectors.toList());
98+
.toList();
12799
}
128100

129101
/**
130102
* Get the properties in this bag.
131103
*
132104
* @return All properties in this bag
133105
*/
134-
public List<DeserBean.DerProperty<T, Object>> getDerProperties() {
106+
List<DeserBean.DerProperty<T, Object>> getDerProperties() {
135107
return Collections.unmodifiableList(Arrays.asList(properties));
136108
}
137109

138-
public DeserBean.DerProperty<T, Object>[] getPropertiesArray() {
110+
DeserBean.DerProperty<T, Object>[] getPropertiesArray() {
139111
return properties;
140112
}
141113

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);
145116
}
146117

147118
private int propertyIndexOfSlow(@NonNull String name) {
@@ -156,45 +127,31 @@ private int propertyIndexOfSlow(@NonNull String name) {
156127
return nameToPropertiesMapping == null ? -1 : nameToPropertiesMapping.getOrDefault(name, -1);
157128
}
158129

159-
public Consumer newConsumer() {
130+
Consumer newConsumer() {
160131
return propertiesMask == 0 ? new ConsumerBig() : new ConsumerSmall();
161132
}
162133

163134
/**
164135
* Properties consumer.
165136
*/
166-
public abstract sealed class Consumer {
137+
abstract sealed class Consumer {
167138
private Consumer() {
168139
}
169140

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-
183141
public DeserBean.DerProperty<T, Object> consume(String name) {
184-
int propertyIndex = propertyIndexOf(name);
142+
int propertyIndex = nameToPosition.get(name, -1);
185143
if (propertyIndex == -1 || isConsumed(propertyIndex)) {
186144
return null;
187145
}
188146
setConsumed(propertyIndex);
189147
return properties[propertyIndex];
190148
}
191149

192-
public DeserBean.DerProperty<T, Object> consume(int propertyIndex) {
150+
public void consume(int propertyIndex) {
193151
if (propertyIndex == -1 || isConsumed(propertyIndex)) {
194-
return null;
152+
return;
195153
}
196154
setConsumed(propertyIndex);
197-
return properties[propertyIndex];
198155
}
199156

200157
public List<DeserBean.DerProperty<T, Object>> getNotConsumed() {
@@ -255,7 +212,7 @@ public boolean isAllConsumed() {
255212
}
256213
}
257214

258-
public static class Builder<T> {
215+
static class Builder<T> {
259216

260217
private final BeanIntrospection<T> beanIntrospection;
261218
private final int[] originalNameToPropertiesMapping;
@@ -264,19 +221,19 @@ public static class Builder<T> {
264221

265222
private final List<DeserBean.DerProperty<T, Object>> mutableProperties;
266223

267-
public Builder(BeanIntrospection<T> beanIntrospection) {
224+
Builder(BeanIntrospection<T> beanIntrospection) {
268225
this(beanIntrospection, beanIntrospection.getBeanProperties().size());
269226
}
270227

271-
public Builder(BeanIntrospection<T> beanIntrospection, int expectedPropertiesSize) {
228+
Builder(BeanIntrospection<T> beanIntrospection, int expectedPropertiesSize) {
272229
this.beanIntrospection = beanIntrospection;
273230
int beanPropertiesSize = beanIntrospection.getBeanProperties().size();
274231
this.originalNameToPropertiesMapping = new int[beanPropertiesSize];
275232
Arrays.fill(originalNameToPropertiesMapping, -1);
276233
this.mutableProperties = new ArrayList<>(expectedPropertiesSize);
277234
}
278235

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) {
280237
int newPropertyIndex = mutableProperties.size();
281238
if (derProperty.beanProperty != null && derProperty.beanProperty.getDeclaringBean() == beanIntrospection && name.equals(derProperty.beanProperty.getName())) {
282239
originalNameToPropertiesMapping[beanIntrospection.propertyIndexOf(name)] = newPropertyIndex;
@@ -295,11 +252,10 @@ public void register(String name, DeserBean.DerProperty<T, Object> derProperty,
295252
}
296253
}
297254
mutableProperties.add(derProperty);
298-
299255
}
300256

301257
@Nullable
302-
public PropertiesBag<T> build() {
258+
PropertiesBag<T> build() {
303259
if (mutableProperties.isEmpty()) {
304260
return null;
305261
}

0 commit comments

Comments
 (0)