Time-consuming tests of several spliced arrays in JAVA

Let’s talk about the conclusion first: ignore other factors and only compare in terms of time consumption. List splicing is the fastest.

There are many ways to splice arrays in JAVA:

1. Purely in the form of array – byte[]

2. Convert to hexadecimal string and use string concatenation – String

3. Convert to hexadecimal string and use StringBuffer to splice – StringBuffer

4. Use the form of collection – ArrayList

The test code is as follows:

package com.zzztest;

import java.util.ArrayList;
import java.util.List;

import com._tool.Hex;
import com._tool.Time;
import com._tool.z;

public class Test {
\t
public static void main(String[] args){
byte[] bs = {1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19,20,21,22, 23,24,25,26,27,28,29,30
,31,32,33,34,35,36,37,38,39,40,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10 };
z.print("0-beg:", Time.getNowTime("0"));
byte[] rs1 = {};
for(int a=0; a<10000; a + + ) {
byte[] bsTemp = new byte[rs1.length + bs.length];
for(int i=0; i< rs1.length ; i + + ) {
bsTemp[i] = rs1[i];
}
for(int i=rs1.length; i<bsTemp.length; i + + ) {
bsTemp[i] = bs[i-rs1.length];
}
rs1 = bsTemp;
}
// z.print("rs1.length:", rs1.length); // -> rs1.length:500000
z.print("1-arr:", Time.getNowTime("0"));
String ss="";
for(int a=0; a<10000; a + + ) {
ss + = Hex.bytesToHexString(bs); // New String(bs) and the following ss.getBytes() cannot be used here. It is found that an error will occur when byte is a negative value.
}
byte[] rs2 = Hex.hexStringToBytes(ss); //ss.getBytes();
// z.print("rs2.length:", rs2.length); // -> rs2.length:500000
z.print("2-str:", Time.getNowTime("0"));
StringBuffer sb = new StringBuffer();
for(int a=0; a<10000; a + + ) {
sb.append(Hex.bytesToHexString(bs));
}
byte[] rs3 = Hex.hexStringToBytes(sb.toString());
// z.print("rs3.length:", rs3.length); // -> rs3.length:500000
z.print("3-buf:", Time.getNowTime("0"));
List<Byte> lb = new ArrayList<>();
for(int a=0; a<10000; a + + ) {
for(int i=0; i<bs.length; i + + ) {
lb.add(bs[i]);
}
}
z.print("4-000:", Time.getNowTime("0"));
byte[] rs4 = new byte[lb.size()];
for(int i=0; i<lb.size(); i + + ) {
rs4[i] = lb.get(i);
}
z.print("4-lst:", Time.getNowTime("0"));
// z.print("rs4.length:",rs4.length); // -> rs4.length:500000
}

First, we comment out the for that loops 10,000 times in each group, and add the following code at the end of the method to print the four results:

z.print("rs1:", rs1);
z.print("rs2:", rs2);
z.print("rs3:", rs3);
z.print("rs4:", rs4);
//Print results:
// 2023-10-11 16:24:41.414/com.zzztest.Test/55 -> rs1:[1,2,3,4,5,6,7,8,9,10,11,12,13 ,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38 ,39,40,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
// 2023-10-11 16:24:41.414/com.zzztest.Test/56 -> rs2:[1,2,3,4,5,6,7,8,9,10,11,12,13 ,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38 ,39,40,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
// 2023-10-11 16:24:41.414/com.zzztest.Test/57 -> rs3:[1,2,3,4,5,6,7,8,9,10,11,12,13 ,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38 ,39,40,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]
// 2023-10-11 16:24:41.415/com.zzztest.Test/58 -> rs4:[1,2,3,4,5,6,7,8,9,10,11,12,13 ,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34,35,36,37,38 ,39,40,-1,-2,-3,-4,-5,-6,-7,-8,-9,-10]

We found that the printed rs1 – rs4 are exactly the same as the original array bs, indicating that all four methods are feasible and can get the correct results.

Note: During testing, it was found that new String(bs) and ss.getBytes() cannot be used because the results obtained are wrong:

Print statement: z.print(“rs2.length:”, rs2.length, “,rs2:”, rs2);

Print result: 2023-10-11 16:47:58.722/com.zzztest.Test/35 -> rs2.length:70,rs2:[1,2,3,4,5,6,7,8,9, 10,11,12,13,14,15,16,17,18,19,20,21,22,23,24,25,26,27,28,29,30,31,32,33,34, 35,36,37,38,39,40,-17,-65,-67,-17,-65,-67,-17,-65,-67,-17,-65,-67,-17 ,-65,-67,-17,-65,-67,-17,-65,-67,-17,-65,-67,-17,-65,-67,-17,-65,- 67]

Here, the length of rs2 is 70, which does not match the length of the original array bs, 50, and the result is incorrect.

The time taken to execute the above code to test the four methods is as follows:

//2023-10-11 16:52:38.837/com.zzztest.Test/15 -> 0-beg:2023-10-11 16:52:38.746
//2023-10-11 16:52:39.599/com.zzztest.Test/28 -> 1-arr:2023-10-11 16:52:39.599
//2023-10-11 16:52:48.484/com.zzztest.Test/35 -> 2-str:2023-10-11 16:52:48.484
//2023-10-11 16:52:48.526/com.zzztest.Test/42 -> 3-buf:2023-10-11 16:52:48.526
//2023-10-11 16:52:48.533/com.zzztest.Test/49 -> 4-000:2023-10-11 16:52:48.532
//2023-10-11 16:52:48.539/com.zzztest.Test/54 -> 4-lst:2023-10-11 16:52:48.539

It can be seen from the results that

Method 1 (pure array splicing) takes: 39599 – 38746 = 853ms

Method 2 (String splicing) takes: 48484 – 39599 = 8885ms

Method 3 (StringBuffer splicing) takes: 48526 – 48484 = 42ms

Method 4 (List collection add) takes time: 48539 – 48526 = 13ms

After repeated testing several times, the time consumption of method 4 fluctuated between 13-16ms. During this period, 4-000 was printed once more because if the final result needs to be converted into a byte array, it will take a total of 13-16ms. If it does not need to be converted into Byte array, you can also use this ArrayList directly, it only takes 6-8ms.

Additional:

The above test only tests the time it takes to execute each method. Other factors are not considered here, such as CPU consumption during method execution, memory consumption, and the amount of garbage generated after method execution.

The two methods of the tool class Hex are as follows:

 //Convert byte array to hexadecimal string
public static String bytesToHexString(byte[] src) {
StringBuilder stringBuilder = new StringBuilder("");
if (src == null || src.length <= 0) {
return "";
}
for (int i = 0; i < src.length; i + + ) {
int v = src[i] & 0xFF;
String hv = Integer.toHexString(v);
if (hv.length() < 2) {
stringBuilder.append(0);
}
stringBuilder.append(hv);
}
return stringBuilder.toString().toUpperCase();
}

// Convert hexadecimal string to byte array
public static byte[] hexStringToBytes(String hexString) {
if (hexString == null || "".equals(hexString)) {
byte[] bs = {};
return bs;
}
hexString = hexString.toUpperCase();
int length = hexString.length() / 2;
char[] hexChars = hexString.toCharArray();
byte[] d = new byte[length];
for (int i = 0; i < length; i + + ) {
int pos = i * 2;
d[i] = (byte) (charToByte(hexChars[pos]) << 4 | charToByte(hexChars[pos + 1]));
}
return d;
}

private static byte charToByte(char c) {
return (byte) "0123456789ABCDEF".indexOf(c);
}