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
pull/17992/head
Mark Hansen 3 months ago committed by Copybara-Service
parent f44ad0b1ae
commit bd1887e436
  1. 34
      java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java

@ -16,6 +16,7 @@ import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collection; import java.util.Collection;
import java.util.List; import java.util.List;
import java.util.RandomAccess;
/** /**
* A partial implementation of the {@link MessageLite} interface which implements as many methods of * A partial implementation of the {@link MessageLite} interface which implements as many methods of
@ -343,19 +344,36 @@ public abstract class AbstractMessageLite<
((ArrayList<T>) list).ensureCapacity(list.size() + ((Collection<T>) values).size()); ((ArrayList<T>) list).ensureCapacity(list.size() + ((Collection<T>) values).size());
} }
int begin = list.size(); int begin = list.size();
for (T value : values) { if (values instanceof List && values instanceof RandomAccess) {
if (value == null) { List<T> valuesList = (List<T>) values;
// encountered a null value so we must undo our modifications prior to throwing int n = valuesList.size();
String message = "Element at index " + (list.size() - begin) + " is null."; // Optimisation: avoid allocating Iterator for RandomAccess lists.
for (int i = list.size() - 1; i >= begin; i--) { for (int i = 0; i < n; i++) {
list.remove(i); T value = valuesList.get(i);
if (value == null) {
resetListAndThrow(list, begin);
}
list.add(value);
}
} else {
for (T value : values) {
if (value == null) {
resetListAndThrow(list, begin);
} }
throw new NullPointerException(message); list.add(value);
} }
list.add(value);
} }
} }
/** Remove elements after index begin from the List and throw NullPointerException. */
private static void resetListAndThrow(List<?> list, int begin) {
String message = "Element at index " + (list.size() - begin) + " is null.";
for (int i = list.size() - 1; i >= begin; i--) {
list.remove(i);
}
throw new NullPointerException(message);
}
/** Construct an UninitializedMessageException reporting missing fields in the given message. */ /** Construct an UninitializedMessageException reporting missing fields in the given message. */
protected static UninitializedMessageException newUninitializedMessageException( protected static UninitializedMessageException newUninitializedMessageException(
MessageLite message) { MessageLite message) {

Loading…
Cancel
Save