Skip to content

Commit 7823aaf

Browse files
Correctly size the map/list from the builder to avoid re-allocation or over-allocation.
PiperOrigin-RevId: 826335491
1 parent 924aa06 commit 7823aaf

File tree

2 files changed

+16
-4
lines changed

2 files changed

+16
-4
lines changed

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

Lines changed: 13 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,6 +123,11 @@ 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+
public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry, int entries) {
127+
int mapCapacity = calculateInitialCapacity(entries);
128+
return new MapField<K, V>(defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>(mapCapacity));
129+
}
130+
126131
private Message convertKeyAndValueToMessage(K key, V value) {
127132
return converter.convertKeyAndValueToMessage(key, value);
128133
}
@@ -132,15 +137,21 @@ private void convertMessageToKeyAndValue(Message message, Map<K, V> map) {
132137
}
133138

134139
private List<Message> convertMapToList(MutabilityAwareMap<K, V> mapData) {
135-
List<Message> listData = new ArrayList<Message>();
140+
List<Message> listData = new ArrayList<Message>(mapData.size());
136141
for (Map.Entry<K, V> entry : mapData.entrySet()) {
137142
listData.add(convertKeyAndValueToMessage(entry.getKey(), entry.getValue()));
138143
}
139144
return listData;
140145
}
141146

147+
private static int calculateInitialCapacity(int entries) {
148+
// Map's default load factor is 0.75. Add 1 to round up.
149+
return (int) Math.ceil(entries / (double) 0.75) + 1;
150+
}
151+
142152
private MutabilityAwareMap<K, V> convertListToMap(List<Message> listData) {
143-
Map<K, V> mapData = new LinkedHashMap<K, V>();
153+
int mapCapacity = calculateInitialCapacity(listData.size());
154+
Map<K, V> mapData = new LinkedHashMap<K, V>(mapCapacity);
144155
for (Message item : listData) {
145156
convertMessageToKeyAndValue(item, mapData);
146157
}

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)