Detailed explanation of two implementations of Java merging arrays

  • 2021-07-26 07:32:15
  • OfStack

Recently, when writing code, I encountered the need to merge two arrays, and suddenly found that I had never used it before, so I studied the way to merge arrays under 1, which is summarized as follows.

1. System. arraycopy () method

(1) Analysis

By reading the JDK source code, I can know that the method prototype is as follows:


public static native void arraycopy(Object src, int srcPos, Object dest, int destPos, int length);

Among them:
src is the source array
srcPos is the starting position of the source array copy
dest is the target array
destPos is the starting position where the target array receives replicated data
length is the length of the copy (the length of the source array that needs to be copied from the copy start position srcPos)

As you can see, this method is local, and we can't understand the principle one step further, but we can know that its function is to copy the elements of length length from the source array to the target array from the starting position srcPos, and the target array receives the copied elements from the position destPos.

(2) Examples


String[] aa = {"11","22","33"};
String[] bb = {"44","55","66"};
String[] cc = {"77","88","99"};

//  Merge two arrays 
String[] dd = new String[aa.length + bb.length];
System.arraycopy(aa, 0, dd, 0, aa.length);
System.arraycopy(bb, 0, dd, aa.length, bb.length);

//  Merge 3 Array of numbers 
String[] ee = new String[aa.length + bb.length + cc.length];
System.arraycopy(aa, 0, ee, 0, aa.length);
System.arraycopy(bb, 0, ee, aa.length, bb.length);
System.arraycopy(cc, 0, ee, aa.length + bb.length, cc.length);

2. ArrayUtils. addAll () method

(1) Analysis

The ArrayUtils tool class is in commons-lang3-3. 5. jar (jar package download address) in apache commons-lang3-3. 5, so you need to import this package before using it. By reading the source code, we can see that the addAll () method essentially calls the System. arraycopy () method.


public static <T> T[] addAll(final T[] array1, final T... array2) {
   if (array1 == null) {
     return clone(array2);
   } else if (array2 == null) {
     return clone(array1);
   }
   final Class<?> type1 = array1.getClass().getComponentType();
   @SuppressWarnings("unchecked") // OK, because array is of type T
   final
   // a Department 
   T[] joinedArray = (T[]) Array.newInstance(type1, array1.length + array2.length);
   System.arraycopy(array1, 0, joinedArray, 0, array1.length);
   try {
     // b Department 
     System.arraycopy(array2, 0, joinedArray, array1.length, array2.length);
   } catch (final ArrayStoreException ase) {
     // Check if problem was due to incompatible types
     /*
     * We do this here, rather than before the copy because:
     * - it would be a wasted check most of the time
     * - safer, in case check turns out to be too strict
     */
     final Class<?> type2 = array2.getClass().getComponentType();
     if (!type1.isAssignableFrom(type2)) {
       throw new IllegalArgumentException("Cannot store " + type2.getName() + " in an array of "
           + type1.getName(), ase);
     }
     throw ase; // No, so rethrow original
   }
   return joinedArray;
 }

The two key parts of this method are a and b marked in the code. At a, an array joinedArray with the length of array1 and array2 is defined by reflection, then array1 is copied to joinedArray, and array2 is copied to joinedArray at b. In addition to these two places, attention should be paid to exception handling. After catching exceptions, it is judged whether type1 inherits from type2, that is, whether the type corresponding to array1 is the same as that corresponding to array2, or whether the type corresponding to array1 is a subclass of the type corresponding to array2, otherwise incompatibility will occur.

(2) Examples


//  Merge two arrays 
String[] ff = ArrayUtils.addAll(aa, bb);

//  Merge multiple strings into an array to form a new array 
String[] gg = ArrayUtils.addAll(aa, "12", "13");
String[] hh = ArrayUtils.addAll(aa, "12", "13", "14");
String[] ii = ArrayUtils.addAll(aa, "12", "13", "14", "15");

//  Merge 3 Array of numbers 
String[] jj = ArrayUtils.addAll(aa, bb);
String[] kk = ArrayUtils.addAll(jj, cc);

It should be noted that the second parameter of addAll () is a variable parameter, which can pass in multiple values of the same type or an array of that type.

(3) Error handling

I encountered one problem in the process of using it, as follows:
Code 1:


String[] ll = ArrayUtils.addAll(aa, bb, cc);

According to the hint found that addAll () return value type is Serializable [], all can not drink String [] compatible. So I changed the code to the following code:
Code 2:


ArrayUtils.addAll(aa, bb, cc);

I thought that if I didn't receive the return value, I wouldn't report an error if I merged it. Although I passed the compilation, I still reported an error when I ran it. The error message is as follows:


Exception in thread "main" java.lang.IllegalArgumentException: Cannot store java.io.Serializable in an array of java.lang.String
  at org.apache.commons.lang3.ArrayUtils.addAll(ArrayUtils.java:5084)
  at com.liu.date20170524.MergeArrays.main(MergeArrays.java:44)
Caused by: java.lang.ArrayStoreException
  at java.lang.System.arraycopy(Native Method)
  at org.apache.commons.lang3.ArrayUtils.addAll(ArrayUtils.java:5073)
  ... 1 more

At that time, I fell into inertial thinking and thought that addAll () method types such as addAll and List could merge multiple lists (in this case, arrays), so I didn't want to understand what the mistake was. It was later discovered that the second parameter of addAll () is of type T, not T [], so more than two arrays cannot be merged. I hope you can take it as a warning.

Reference: https://www.ofstack.com/article/129962. htm


Related articles: