Search code examples
javaarraylistnanotime

Why insertion into empty ArrayList takes more time than insertion into non-empty ArrayList?


I ran my profiler program for 1000 iterations to calculate the average time taken to insert into Empty ArrayList and average time to insert into Non-Empty ArrayList. I ran my profiler program for ArrayList<Item>, where Item class is

class Item{
  int id;
  String name;
}

And the profiler program is something like

main(){
  final int iterations = 1000;

  /**** Empty List Insert ****/
  int id = 0;
  long[] timerecords = new long[iterations];
  ArrayList<Item> list = new ArrayList<>();
  for (int i = 0; i < iterations; i++) {
      long stime = System.nanoTime(); //Start Time
      list.add(new Item(id, "A"));
      long elapsedTime = System.nanoTime() - stime; //Elapsed time
      timerecords[i] = elapsedTime; //Record Elapsed time

      //reset
      list.clear();
  }
  System.out.println("Empty List Insert Takes = " + getAverageTime(timerecords) + " nanoseconds");

  /**** Non-Empty List Insert ****/
  list = new ArrayList<>();
  timerecords = new long[iterations];
  //Insert some Items
  list.add(new Item(id++, "B")); list.add(new Item(id++, "R"));
  list.add(new Item(id++, "H")); list.add(new Item(id++, "C")); 

  for (int i = 0; i < iterations; i++) {    
        Item item = new Item(id, "A");
        long stime = System.nanoTime(); //Start Time
        list.add(item);
        long elapsedTime = System.nanoTime() - stime; //Elapsed time
        timerecords[i] = elapsedTime; //Record Elapsed time

        //reset
        list.remove(item);
  }
  System.out.println("Non-Empty List Insert Takes = " + getAverageTime(timerecords) + " nanoseconds");
}

where getAverageTime(long [] timerecords) method returns average time in double. After running this program several times, I observed insertion into empty ArrayList takes more time than insertion into non-empty ArrayList. One such run output is

Empty List Insert Takes = 1027.781 nanoseconds
Non-Empty List Insert Takes = 578.825 nanoseconds

Whats the reason behind this ?


Solution

  • The difference comes because of the instance creation (new Item()).

      long stime = System.nanoTime(); //Start Time
      list.add(new Item(id, "A")); // at this point two things are happening
      // creation of instance & addition into ArrayList
      // both takes their own time.
    
      long elapsedTime = System.nanoTime() - stime; //Elapsed time
    

    The point where u create stime variable is the point where the timer starts. You are certainly adding new item to the list. But in 1st case, before u do System.nanoTime(); u are calling new operator on Item while adding (after you assign stime variable) which is taking that extra time. While in 2nd case, you are doing it before u r doing System.nanoTime();

        Item item = new Item(id, "A");
        long stime = System.nanoTime(); //Start Time
        list.add(item);
        long elapsedTime = System.nanoTime() - stime; //Elapsed time
    

    so, only adding of item object to the ArrayList time is captured.