Skip to content

Commit 35b07e1

Browse files
Correctly size the map/list from the builder to avoid re-allocation or over-allocation.
PiperOrigin-RevId: 826335491
1 parent 4986a77 commit 35b07e1

File tree

2 files changed

+17
-4
lines changed

2 files changed

+17
-4
lines changed

java/core/src/main/java/com/google/protobuf/MapField.java

Lines changed: 14 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,10 @@ public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) {
123123
return new MapField<K, V>(defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>());
124124
}
125125

126+
static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry, int entries) {
127+
return new MapField<K, V>(defaultEntry, StorageMode.MAP, newLinkedHashMapWithCapacity(entries));
128+
}
129+
126130
private Message convertKeyAndValueToMessage(K key, V value) {
127131
return converter.convertKeyAndValueToMessage(key, value);
128132
}
@@ -132,15 +136,23 @@ private void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
132136
}
133137

134138
private List<Message> convertMapToList(MutabilityAwareMap<K, V> mapData) {
135-
List<Message> listData = new ArrayList<Message>();
139+
List<Message> listData = new ArrayList<Message>(mapData.size());
136140
for (Map.Entry<K, V> entry : mapData.entrySet()) {
137141
listData.add(convertKeyAndValueToMessage(entry.getKey(), entry.getValue()));
138142
}
139143
return listData;
140144
}
141145

146+
private static <K, V> LinkedHashMap<K, V> newLinkedHashMapWithCapacity(int entries) {
147+
// When minimum supported Java version is 19, this method can be replaced with
148+
// LinkedHashMap.newLinkedHashMap
149+
// Map's default load factor is 0.75.
150+
int mapCapacity = (int) Math.ceil(entries / (double) 0.75);
151+
return new LinkedHashMap<K, V>(mapCapacity);
152+
}
153+
142154
private MutabilityAwareMap<K, V> convertListToMap(List<Message> listData) {
143-
Map<K, V> mapData = new LinkedHashMap<K, V>();
155+
Map<K, V> mapData = newLinkedHashMapWithCapacity(listData.size());
144156
for (Message item : listData) {
145157
convertMessageToKeyAndValue(item, mapData);
146158
}

java/core/src/main/java/com/google/protobuf/MapFieldBuilder.java

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -189,9 +189,10 @@ public MapFieldBuilder<KeyT, MessageOrBuilderT, MessageT, BuilderT> copy() {
189189

190190
/** Converts this MapFieldBuilder to a MapField. */
191191
public MapField<KeyT, MessageT> build(MapEntry<KeyT, MessageT> defaultEntry) {
192-
MapField<KeyT, MessageT> mapField = MapField.newMapField(defaultEntry);
192+
Map<KeyT, MessageOrBuilderT> builderMap = ensureBuilderMap();
193+
MapField<KeyT, MessageT> mapField = MapField.newMapField(defaultEntry, builderMap.size());
193194
Map<KeyT, MessageT> map = mapField.getMutableMap();
194-
for (Map.Entry<KeyT, MessageOrBuilderT> entry : ensureBuilderMap().entrySet()) {
195+
for (Map.Entry<KeyT, MessageOrBuilderT> entry : builderMap.entrySet()) {
195196
map.put(entry.getKey(), converter.build(entry.getValue()));
196197
}
197198
mapField.makeImmutable();

0 commit comments

Comments
 (0)