Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it faster (or better) to declare an array inline in Java?

Consider the following two method calls that are nearly equivalent. Take note of the way the byte array is declared and allocated on both.

void Method1()
{
    byte [] bytearray = new byte[16];

    /* some code */

}

void Method2()
{
    byte [] bytearray = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};

    /* some code */    
}

In both cases, assume that when Method1 and Method2 return, "bytearray" is a candidate for garbage collection since none of the code that manipulates the bytearray variable will be holding a reference past the end of the method itself.

Does Method2 operate any faster (or differently) by avoiding the call to "new"? Or are the two implementations above equivalent? In either case, can the Java compiler or runtime make an optimization to avoid the overhead of hitting the memory allocator for this short-lived temporary buffer?

like image 832
selbie Avatar asked Dec 03 '13 10:12

selbie


People also ask

Why array is faster than list Java?

An array is faster and that is because ArrayList uses a fixed amount of array. However when you add an element to the ArrayList and it overflows. It creates a new Array and copies every element from the old one to the new one.

Are arrays more efficient than lists Java?

Performance and speed are important factors for deciding which method to use. About that, Arrays perform better than ArrayLists.

How do you initialize an entire array with value?

int num[5] = {1, 1, 1, 1, 1}; This will initialize the num array with value 1 at all index. The array will be initialized to 0 in case we provide empty initializer list or just specify 0 in the initializer list. Designated Initializer: This initializer is used when we want to initialize a range with the same value.


2 Answers

Which form is the fastest? Depends on the JIT - it's possible they're equivalent. Very few, if any, programs will ever notice the difference if there is any.

Which form is the best? Almost invariably, the one that leaves your program more readable.

But is there any actual difference, regardless of if we'll ever notice? Let's have a look!

class ArrayTest {

    public int[] withNew() {
        int[] arr = new int[4];
        return arr;
    }

    public int[] withInitializer() {
        int[] arr = {0, 0, 0, 0};
        return arr;
    }

}

We disassemble this with javap -c ArrayTest:

Compiled from "ArrayTest.java"
class ArrayTest {
  ArrayTest();
    Code:
       0: aload_0       
       1: invokespecial #1                  // Method java/lang/Object."<init>":()V
       4: return        

  public int[] withNew();
    Code:
       0: iconst_4      
       1: newarray       int
       3: astore_1      
       4: aload_1       
       5: areturn       

  public int[] withInitializer();
    Code:
       0: iconst_4      
       1: newarray       int
       3: dup           
       4: iconst_0      
       5: iconst_0      
       6: iastore       
       7: dup           
       8: iconst_1      
       9: iconst_0      
      10: iastore       
      11: dup           
      12: iconst_2      
      13: iconst_0      
      14: iastore       
      15: dup           
      16: iconst_3      
      17: iconst_0      
      18: iastore       
      19: astore_1      
      20: aload_1       
      21: areturn       
}

Nope, they're not the same in this case - using the initializer form causes the slots to be individually set to 0, which is kind of pointless since they're already zeroed by the array allocation. So, it's basically equivalent to this:

public int[] withNewAndSettingExplicitly() {
    int[] arr = new int[4];
    arr[0] = 0;
    arr[1] = 0;
    arr[2] = 0;
    arr[3] = 0;
    return arr;
}

although that compiles to yet another set of byte code, which is mostly the same but not quite:

  public int[] withNewAndSettingExplicitly();
    Code:
       0: iconst_4      
       1: newarray       int
       3: astore_1      
       4: aload_1       
       5: iconst_0      
       6: iconst_0      
       7: iastore       
       8: aload_1       
       9: iconst_1      
      10: iconst_0      
      11: iastore       
      12: aload_1       
      13: iconst_2      
      14: iconst_0      
      15: iastore       
      16: aload_1       
      17: iconst_3      
      18: iconst_0      
      19: iastore       
      20: aload_1       
      21: areturn 

Thus, the moral of the story is this: If you want all elements set to 0, you're generating less bytecode with new int[size] (which may or may not be faster), but you also have to type less (which imho is a big win). If you want to set the values in the array directly when you're allocating it, use whatever looks best in your code, because the generated code will be pretty much the same whatever form you choose.

Now, to answer your actual questions:

Does Method2 operate any faster (or differently) by avoiding the call to "new"?

As we saw, the new is just hidden behind the initializer syntax (look for the newarray op code). By the way, allocation is extremely cheap in the JVM (generational garbage collectors have that pleasant side effect).

Or are the two implementations above equivalent?

As we saw - not quite, but it's unlikely anyone will ever notice the difference.

In either case, can the Java compiler or runtime make an optimization to avoid the overhead of hitting the memory allocator for this short-lived temporary buffer?

Again - allocation is cheap, so don't worry. Nevertheless, recent JVMs have this little feature called escape analysis which may result in the array being stack allocated rather than heap allocated.

like image 127
gustafc Avatar answered Oct 19 '22 15:10

gustafc


There is no difference between both the ways. It's just 'Syntactic sugar' in syntax.

like image 32
Suresh Atta Avatar answered Oct 19 '22 16:10

Suresh Atta