Skip to content

Commit bd1887e

Browse files
mhansencopybara-github
authored andcommitted
Avoid allocating iterators when calling Message.Builder.addAllFoo(RandomAccess List)
I've tried to keep the hot part of the loop (not null) in the loop without requiring an extra function call, and only extracted the cold part (null handling) to avoid repetition. PiperOrigin-RevId: 670760103
1 parent f44ad0b commit bd1887e

File tree

1 file changed

+26
-8
lines changed

1 file changed

+26
-8
lines changed

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

Lines changed: 26 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
import java.util.ArrayList;
1717
import java.util.Collection;
1818
import java.util.List;
19+
import java.util.RandomAccess;
1920

2021
/**
2122
* A partial implementation of the {@link MessageLite} interface which implements as many methods of
@@ -343,19 +344,36 @@ private static <T> void addAllCheckingNulls(Iterable<T> values, List<? super T>
343344
((ArrayList<T>) list).ensureCapacity(list.size() + ((Collection<T>) values).size());
344345
}
345346
int begin = list.size();
346-
for (T value : values) {
347-
if (value == null) {
348-
// encountered a null value so we must undo our modifications prior to throwing
349-
String message = "Element at index " + (list.size() - begin) + " is null.";
350-
for (int i = list.size() - 1; i >= begin; i--) {
351-
list.remove(i);
347+
if (values instanceof List && values instanceof RandomAccess) {
348+
List<T> valuesList = (List<T>) values;
349+
int n = valuesList.size();
350+
// Optimisation: avoid allocating Iterator for RandomAccess lists.
351+
for (int i = 0; i < n; i++) {
352+
T value = valuesList.get(i);
353+
if (value == null) {
354+
resetListAndThrow(list, begin);
355+
}
356+
list.add(value);
357+
}
358+
} else {
359+
for (T value : values) {
360+
if (value == null) {
361+
resetListAndThrow(list, begin);
352362
}
353-
throw new NullPointerException(message);
363+
list.add(value);
354364
}
355-
list.add(value);
356365
}
357366
}
358367

368+
/** Remove elements after index begin from the List and throw NullPointerException. */
369+
private static void resetListAndThrow(List<?> list, int begin) {
370+
String message = "Element at index " + (list.size() - begin) + " is null.";
371+
for (int i = list.size() - 1; i >= begin; i--) {
372+
list.remove(i);
373+
}
374+
throw new NullPointerException(message);
375+
}
376+
359377
/** Construct an UninitializedMessageException reporting missing fields in the given message. */
360378
protected static UninitializedMessageException newUninitializedMessageException(
361379
MessageLite message) {

0 commit comments

Comments
 (0)