Avoid boxing/unboxing `varint`, `fixed32`, and `fixed64` fields in `UnknownFieldSet.Field`

PiperOrigin-RevId: 810678393
diff --git a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
index f5435af..55e0e5e 100644
--- a/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/BooleanArrayList.java
@@ -55,6 +55,17 @@
     this.size = size;
   }
 
+  /**
+   * Constructs a new mutable {@code BooleanArrayList} containing the same elements as {@code
+   * other}.
+   */
+  BooleanArrayList(BooleanArrayList other, boolean isMutable) {
+    this(
+        other.size == 0 ? EMPTY_ARRAY : Arrays.copyOf(other.array, other.size),
+        other.size,
+        isMutable);
+  }
+
   @Override
   protected void removeRange(int fromIndex, int toIndex) {
     ensureIsMutable();
diff --git a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
index 4198cd8..241acd5 100644
--- a/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/DoubleArrayList.java
@@ -54,6 +54,16 @@
     this.size = size;
   }
 
+  /**
+   * Constructs a new mutable {@code DoubleArrayList} containing the same elements as {@code other}.
+   */
+  DoubleArrayList(DoubleArrayList other, boolean isMutable) {
+    this(
+        other.size == 0 ? EMPTY_ARRAY : Arrays.copyOf(other.array, other.size),
+        other.size,
+        isMutable);
+  }
+
   @Override
   protected void removeRange(int fromIndex, int toIndex) {
     ensureIsMutable();
diff --git a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
index c705754..87336a6 100644
--- a/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/FloatArrayList.java
@@ -54,6 +54,16 @@
     this.size = size;
   }
 
+  /**
+   * Constructs a new mutable {@code FloatArrayList} containing the same elements as {@code other}.
+   */
+  FloatArrayList(FloatArrayList other, boolean isMutable) {
+    this(
+        other.size == 0 ? EMPTY_ARRAY : Arrays.copyOf(other.array, other.size),
+        other.size,
+        isMutable);
+  }
+
   @Override
   protected void removeRange(int fromIndex, int toIndex) {
     ensureIsMutable();
diff --git a/java/core/src/main/java/com/google/protobuf/IntArrayList.java b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
index 73e03a0..76192c8 100644
--- a/java/core/src/main/java/com/google/protobuf/IntArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/IntArrayList.java
@@ -54,6 +54,16 @@
     this.size = size;
   }
 
+  /**
+   * Constructs a new mutable {@code IntArrayList} containing the same elements as {@code other}.
+   */
+  IntArrayList(IntArrayList other, boolean isMutable) {
+    this(
+        other.size == 0 ? EMPTY_ARRAY : Arrays.copyOf(other.array, other.size),
+        other.size,
+        isMutable);
+  }
+
   @Override
   protected void removeRange(int fromIndex, int toIndex) {
     ensureIsMutable();
diff --git a/java/core/src/main/java/com/google/protobuf/LongArrayList.java b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
index e4725c5..e7cff6f 100644
--- a/java/core/src/main/java/com/google/protobuf/LongArrayList.java
+++ b/java/core/src/main/java/com/google/protobuf/LongArrayList.java
@@ -54,6 +54,16 @@
     this.size = size;
   }
 
+  /**
+   * Constructs a new mutable {@code LongArrayList} containing the same elements as {@code other}.
+   */
+  LongArrayList(LongArrayList other, boolean isMutable) {
+    this(
+        other.size == 0 ? EMPTY_ARRAY : Arrays.copyOf(other.array, other.size),
+        other.size,
+        isMutable);
+  }
+
   @Override
   protected void removeRange(int fromIndex, int toIndex) {
     ensureIsMutable();
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
index de50583..9846bfa 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -12,10 +12,10 @@
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.util.ArrayList;
-import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import java.util.Map;
+import java.util.Objects;
 import java.util.TreeMap;
 
 /**
@@ -749,17 +749,23 @@
       if (!(other instanceof Field)) {
         return false;
       }
-      return Arrays.equals(getIdentityArray(), ((Field) other).getIdentityArray());
+      Field that = (Field) other;
+      return Objects.equals(varint, that.varint)
+          && Objects.equals(fixed32, that.fixed32)
+          && Objects.equals(fixed64, that.fixed64)
+          && Objects.equals(lengthDelimited, that.lengthDelimited)
+          && Objects.equals(group, that.group);
     }
 
     @Override
     public int hashCode() {
-      return Arrays.hashCode(getIdentityArray());
-    }
-
-    /** Returns the array of objects to be used to uniquely identify this {@link Field} instance. */
-    private Object[] getIdentityArray() {
-      return new Object[] {varint, fixed32, fixed64, lengthDelimited, group};
+      int result = 1;
+      result = 31 * result + Objects.hashCode(varint);
+      result = 31 * result + Objects.hashCode(fixed32);
+      result = 31 * result + Objects.hashCode(fixed64);
+      result = 31 * result + Objects.hashCode(lengthDelimited);
+      result = 31 * result + Objects.hashCode(group);
+      return result;
     }
 
     /**
@@ -783,15 +789,15 @@
     @SuppressWarnings({"ForeachList", "ForeachListWithUserVar"}) // No iterator allocation.
     public void writeTo(int fieldNumber, CodedOutputStream output) throws IOException {
       for (int i = 0; i < varint.size(); i++) {
-        long value = varint.get(i);
+        long value = varint.getLong(i);
         output.writeUInt64(fieldNumber, value);
       }
       for (int i = 0; i < fixed32.size(); i++) {
-        int value = fixed32.get(i);
+        int value = fixed32.getInt(i);
         output.writeFixed32(fieldNumber, value);
       }
       for (int i = 0; i < fixed64.size(); i++) {
-        long value = fixed64.get(i);
+        long value = fixed64.getLong(i);
         output.writeFixed64(fieldNumber, value);
       }
       for (int i = 0; i < lengthDelimited.size(); i++) {
@@ -809,15 +815,15 @@
     public int getSerializedSize(int fieldNumber) {
       int result = 0;
       for (int i = 0; i < varint.size(); i++) {
-        long value = varint.get(i);
+        long value = varint.getLong(i);
         result += CodedOutputStream.computeUInt64Size(fieldNumber, value);
       }
       for (int i = 0; i < fixed32.size(); i++) {
-        int value = fixed32.get(i);
+        int value = fixed32.getInt(i);
         result += CodedOutputStream.computeFixed32Size(fieldNumber, value);
       }
       for (int i = 0; i < fixed64.size(); i++) {
-        long value = fixed64.get(i);
+        long value = fixed64.getLong(i);
         result += CodedOutputStream.computeFixed64Size(fieldNumber, value);
       }
       for (int i = 0; i < lengthDelimited.size(); i++) {
@@ -901,9 +907,9 @@
       return result;
     }
 
-    private List<Long> varint;
-    private List<Integer> fixed32;
-    private List<Long> fixed64;
+    private LongArrayList varint;
+    private IntArrayList fixed32;
+    private LongArrayList fixed64;
     private List<ByteString> lengthDelimited;
     private List<UnknownFieldSet> group;
 
@@ -931,17 +937,17 @@
         if (result.varint == null) {
           copy.varint = null;
         } else {
-          copy.varint = new ArrayList<>(result.varint);
+          copy.varint = new LongArrayList(result.varint, /* isMutable= */ true);
         }
         if (result.fixed32 == null) {
           copy.fixed32 = null;
         } else {
-          copy.fixed32 = new ArrayList<>(result.fixed32);
+          copy.fixed32 = new IntArrayList(result.fixed32, /* isMutable= */ true);
         }
         if (result.fixed64 == null) {
           copy.fixed64 = null;
         } else {
-          copy.fixed64 = new ArrayList<>(result.fixed64);
+          copy.fixed64 = new LongArrayList(result.fixed64, /* isMutable= */ true);
         }
         if (result.lengthDelimited == null) {
           copy.lengthDelimited = null;
@@ -965,19 +971,19 @@
       public Field build() {
         Field built = new Field();
         if (result.varint == null) {
-          built.varint = Collections.emptyList();
+          built.varint = LongArrayList.emptyList();
         } else {
-          built.varint = Collections.unmodifiableList(new ArrayList<>(result.varint));
+          built.varint = new LongArrayList(result.varint, /* isMutable= */ false);
         }
         if (result.fixed32 == null) {
-          built.fixed32 = Collections.emptyList();
+          built.fixed32 = IntArrayList.emptyList();
         } else {
-          built.fixed32 = Collections.unmodifiableList(new ArrayList<>(result.fixed32));
+          built.fixed32 = new IntArrayList(result.fixed32, /* isMutable= */ false);
         }
         if (result.fixed64 == null) {
-          built.fixed64 = Collections.emptyList();
+          built.fixed64 = LongArrayList.emptyList();
         } else {
-          built.fixed64 = Collections.unmodifiableList(new ArrayList<>(result.fixed64));
+          built.fixed64 = new LongArrayList(result.fixed64, /* isMutable= */ false);
         }
         if (result.lengthDelimited == null) {
           built.lengthDelimited = Collections.emptyList();
@@ -1007,19 +1013,19 @@
       public Builder mergeFrom(Field other) {
         if (!other.varint.isEmpty()) {
           if (result.varint == null) {
-            result.varint = new ArrayList<Long>();
+            result.varint = new LongArrayList();
           }
           result.varint.addAll(other.varint);
         }
         if (!other.fixed32.isEmpty()) {
           if (result.fixed32 == null) {
-            result.fixed32 = new ArrayList<Integer>();
+            result.fixed32 = new IntArrayList();
           }
           result.fixed32.addAll(other.fixed32);
         }
         if (!other.fixed64.isEmpty()) {
           if (result.fixed64 == null) {
-            result.fixed64 = new ArrayList<>();
+            result.fixed64 = new LongArrayList();
           }
           result.fixed64.addAll(other.fixed64);
         }
@@ -1041,27 +1047,27 @@
       /** Add a varint value. */
       public Builder addVarint(long value) {
         if (result.varint == null) {
-          result.varint = new ArrayList<>();
+          result.varint = new LongArrayList();
         }
-        result.varint.add(value);
+        result.varint.addLong(value);
         return this;
       }
 
       /** Add a fixed32 value. */
       public Builder addFixed32(int value) {
         if (result.fixed32 == null) {
-          result.fixed32 = new ArrayList<>();
+          result.fixed32 = new IntArrayList();
         }
-        result.fixed32.add(value);
+        result.fixed32.addInt(value);
         return this;
       }
 
       /** Add a fixed64 value. */
       public Builder addFixed64(long value) {
         if (result.fixed64 == null) {
-          result.fixed64 = new ArrayList<>();
+          result.fixed64 = new LongArrayList();
         }
-        result.fixed64.add(value);
+        result.fixed64.addLong(value);
         return this;
       }