diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java index dde30c1b7e..15c783195d 100644 --- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java +++ b/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.Collection; import java.util.List; +import java.util.RandomAccess; /** * A partial implementation of the {@link MessageLite} interface which implements as many methods of @@ -343,19 +344,36 @@ public abstract class AbstractMessageLite< ((ArrayList) list).ensureCapacity(list.size() + ((Collection) values).size()); } int begin = list.size(); - for (T value : values) { - if (value == null) { - // encountered a null value so we must undo our modifications prior to throwing - String message = "Element at index " + (list.size() - begin) + " is null."; - for (int i = list.size() - 1; i >= begin; i--) { - list.remove(i); + if (values instanceof List && values instanceof RandomAccess) { + List valuesList = (List) values; + int n = valuesList.size(); + // Optimisation: avoid allocating Iterator for RandomAccess lists. + for (int i = 0; i < n; 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. */ protected static UninitializedMessageException newUninitializedMessageException( MessageLite message) {