How can I repeat the elements of an array in Java?
For example, given the array {a,b,c,d,e,f}
and a number n
, I want to produce an n
-element array that looks like {a,b,c,d,e,f,a,b,c,d,e,f,a,b,c,...}
.
If I knew the length of the input and output arrays in advance, I could just write something like this:
int a=input[0], b=input[1], c=input[2], d=input[3], e=input[4], f=input[5];
int[] array = new int[n];
array[0]=a; array[1]=b; array[2]=c; array[3]=d; array[4]=e; array[5]=f;
array[6]=a; array[7]=b; array[8]=c; array[9]=d; array[10]=e; array[11]=f;
array[12]=a; array[13]=b; array[14]=c; // .. and so on
But how can I do this if I don't know the lengths yet? I assume I would have to use a loop of some kind, but I'm not sure how to write one. Or is there some built-in way to repeat an array in Java, like some other languages have?
This implementation is much cleaner and faster than the others shown here.
public static <T> T[] repeat(T[] arr, int newLength) {
T[] dup = Arrays.copyOf(arr, newLength);
for (int last = arr.length; last != 0 && last < newLength; last <<= 1) {
System.arraycopy(dup, 0, dup, last, Math.min(last << 1, newLength) - last);
}
return dup;
}
System.arraycopy
is a native call. Therefore it is very fast but it doesn't mean it is the fastest way.
Every other solution copys the array element by element. My solution copys larger blocks. Every iteration duplicates the existing elements in the array which means the loop will run at most log2(n) times.
Here is my benchmark code to reproduce the results:
import org.openjdk.jmh.annotations.Benchmark;
import org.openjdk.jmh.annotations.BenchmarkMode;
import org.openjdk.jmh.annotations.Fork;
import org.openjdk.jmh.annotations.Measurement;
import org.openjdk.jmh.annotations.Mode;
import org.openjdk.jmh.annotations.OutputTimeUnit;
import org.openjdk.jmh.annotations.Scope;
import org.openjdk.jmh.annotations.State;
import org.openjdk.jmh.annotations.Threads;
import org.openjdk.jmh.annotations.Warmup;
@Fork(3)
@BenchmarkMode(Mode.AverageTime)
@Measurement(iterations = 10, timeUnit = TimeUnit.NANOSECONDS)
@State(Scope.Benchmark)
@Threads(1)
@Warmup(iterations = 5, timeUnit = TimeUnit.NANOSECONDS)
@OutputTimeUnit(TimeUnit.NANOSECONDS)
public class MyBenchmark {
private static final String[] TEST_ARRAY = { "a", "b", "c", "d", "e", "f" };
private static final int NEW_LENGTH = 10_000;
@Benchmark
public String[] testMethod() {
String[] dup = Arrays.copyOf(TEST_ARRAY, NEW_LENGTH);
for (int last = TEST_ARRAY.length; last != 0 && last < NEW_LENGTH; last <<= 1) {
System.arraycopy(dup, 0, dup, last, Math.min(last << 1, NEW_LENGTH) - last);
}
return dup;
}
@Benchmark
public String[] testMethod1() {
String[] arr = new String[NEW_LENGTH];
for (int i = 0; i < NEW_LENGTH; i++) {
arr[i] = TEST_ARRAY[i % TEST_ARRAY.length];
}
return arr;
}
@Benchmark
public String[] testMethod2() {
List<String> initialLetters = Arrays.asList(TEST_ARRAY);
List<String> results = new ArrayList<>();
int indexOfLetterToAdd = 0;
for (int i = 0; i < 10000; i++) {
results.add(initialLetters.get(indexOfLetterToAdd++));
if (indexOfLetterToAdd == initialLetters.size()) {
indexOfLetterToAdd = 0;
}
}
return results.toArray(new String[results.size()]);
}
@Benchmark
public String[] testMethod3() {
String result[] = new String[NEW_LENGTH];
for (int i = 0, j = 0; i < NEW_LENGTH && j < TEST_ARRAY.length; i++, j++) {
result[i] = TEST_ARRAY[j];
if (j == TEST_ARRAY.length - 1) {
j = -1;
}
}
return result;
}
@Benchmark
public String[] testMethod4() {
String[] result = Stream.iterate(TEST_ARRAY, x -> x).flatMap(x -> Stream.of(TEST_ARRAY)).limit(NEW_LENGTH)
.toArray(String[]::new);
return result;
}
}
Benchmark Mode Cnt Score Error Units
MyBenchmark.testMethod avgt 30 4154,553 ± 11,242 ns/op
MyBenchmark.testMethod1 avgt 30 19273,717 ± 235,547 ns/op
MyBenchmark.testMethod2 avgt 30 71079,139 ± 2686,136 ns/op
MyBenchmark.testMethod3 avgt 30 18307,368 ± 202,520 ns/op
MyBenchmark.testMethod4 avgt 30 68898,278 ± 2488,104 ns/op
I rephrased this question and answered it with more precise benchmarks as it was suggested. Fastest way to create new array with length N and fill it by repeating a given array
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With