Fastest way to set all values of an array?

后端 未结 14 2251
悲哀的现实
悲哀的现实 2020-12-04 17:47

I have a char [], and I want to set the value of every index to the same char value.
There is the obvious way to do it (iteration):

<         


        
相关标签:
14条回答
  • 2020-12-04 18:00

    If you have another array of char, char[] b and you want to replace c with b, you can use c=b.clone();.

    0 讨论(0)
  • 2020-12-04 18:05

    System.arraycopy is my answer. Please let me know is there any better ways. Thx

    private static long[] r1 = new long[64];
    private static long[][] r2 = new long[64][64];
    
    /**Proved:
     * {@link Arrays#fill(long[], long[])} makes r2 has 64 references to r1 - not the answer;
     * {@link Arrays#fill(long[], long)} sometimes slower than deep 2 looping.<br/>
     */
    private static void testFillPerformance() {
        SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
        System.out.println(sdf.format(new Date()));
        Arrays.fill(r1, 0l);
    
        long stamp0 = System.nanoTime();
        //      Arrays.fill(r2, 0l); -- exception
        long stamp1 = System.nanoTime();
        //      System.out.println(String.format("Arrays.fill takes %s nano-seconds.", stamp1 - stamp0));
    
        stamp0 = System.nanoTime();
        for (int i = 0; i < 64; i++) {
            for (int j = 0; j < 64; j++)
                r2[i][j] = 0l;
        }
        stamp1 = System.nanoTime();
        System.out.println(String.format("Arrays' 2-looping takes %s nano-seconds.", stamp1 - stamp0));
    
        stamp0 = System.nanoTime();
        for (int i = 0; i < 64; i++) {
            System.arraycopy(r1, 0, r2[i], 0, 64);
        }
        stamp1 = System.nanoTime();
        System.out.println(String.format("System.arraycopy looping takes %s nano-seconds.", stamp1 - stamp0));
    
        stamp0 = System.nanoTime();
        Arrays.fill(r2, r1);
        stamp1 = System.nanoTime();
        System.out.println(String.format("One round Arrays.fill takes %s nano-seconds.", stamp1 - stamp0));
    
        stamp0 = System.nanoTime();
        for (int i = 0; i < 64; i++)
            Arrays.fill(r2[i], 0l);
        stamp1 = System.nanoTime();
        System.out.println(String.format("Two rounds Arrays.fill takes %s nano-seconds.", stamp1 - stamp0));
    }
    

    12:33:18
    Arrays' 2-looping takes 133536 nano-seconds.
    System.arraycopy looping takes 22070 nano-seconds.
    One round Arrays.fill takes 9777 nano-seconds.
    Two rounds Arrays.fill takes 93028 nano-seconds.

    12:33:38
    Arrays' 2-looping takes 133816 nano-seconds.
    System.arraycopy looping takes 22070 nano-seconds.
    One round Arrays.fill takes 17042 nano-seconds.
    Two rounds Arrays.fill takes 95263 nano-seconds.

    12:33:51
    Arrays' 2-looping takes 199187 nano-seconds.
    System.arraycopy looping takes 44140 nano-seconds.
    One round Arrays.fill takes 19555 nano-seconds.
    Two rounds Arrays.fill takes 449219 nano-seconds.

    12:34:16
    Arrays' 2-looping takes 199467 nano-seconds.
    System.arraycopy looping takes 42464 nano-seconds.
    One round Arrays.fill takes 17600 nano-seconds.
    Two rounds Arrays.fill takes 170971 nano-seconds.

    12:34:26
    Arrays' 2-looping takes 198907 nano-seconds.
    System.arraycopy looping takes 24584 nano-seconds.
    One round Arrays.fill takes 10616 nano-seconds.
    Two rounds Arrays.fill takes 94426 nano-seconds.

    0 讨论(0)
  • 2020-12-04 18:06

    Java Programmer's FAQ Part B Sect 6 suggests:

    public static void bytefill(byte[] array, byte value) {
        int len = array.length;
        if (len > 0)
        array[0] = value;
        for (int i = 1; i < len; i += i)
            System.arraycopy( array, 0, array, i,
                ((len - i) < i) ? (len - i) : i);
    }
    

    This essentially makes log2(array.length) calls to System.arraycopy which hopefully utilizes an optimized memcpy implementation.

    However, is this technique still required on modern Java JITs such as the Oracle/Android JIT?

    0 讨论(0)
  • 2020-12-04 18:06

    Arrays.fill is the best option for general purpose use. If you need to fill large arrays though as of latest idk 1.8 u102, there is a faster way that leverages System.arraycopy. You can take a look at this alternate Arrays.fill implementation:

    According to the JMH benchmarks you can get almost 2x performance boost for large arrays (1000 +)

    In any case, these implementations should be used only where needed. JDKs Arrays.fill should be the preferred choice.

    0 讨论(0)
  • 2020-12-04 18:07

    Arrays.fill(myArray, 'c');

    Arrays.fill

    Although it is quite possible that this is doing the loop in the background and is therefore not any more efficient than what you have (other than the lines of code savings). If you really care about efficiency, try the following in comparison to the above:

    int size = 50;
    char[] array = new char[size];
    for (int i=0; i<size; i++){
      array[i] = 'c';
    }
    

    Notice that the above doesn't call array.size() for each iteration.

    0 讨论(0)
  • 2020-12-04 18:08

    Try Arrays.fill(c, f) : Arrays javadoc

    0 讨论(0)
提交回复
热议问题