8

I need to insert a element of type Person (my own defined class) in an ArrayList at index i

I know I can use add(int index, E element).

But is there any efficient method to do this as in my list it is taking around 1.5 ms on an average (data collected over 1000 insertion and then average).

Duncan Jones
  • 67,400
  • 29
  • 193
  • 254
learner
  • 1,952
  • 7
  • 33
  • 62
  • Well how big is your list? If you insert data early into a very large list, you'll be copying a lot of data... – Jon Skeet Jun 17 '13 at 11:12
  • Do you mean - is there a list implementation that is more efficient for insertion? – Duncan Jones Jun 17 '13 at 11:12
  • I'd be surprised if there would be a more efficient way using ArrayList. Core functions should be optomized pretty well. Plus do you consider 1.5 ms slow? – Peter Jaloveczki Jun 17 '13 at 11:12
  • 5
    `LinkedList` is much more appropriate for insertion/deletion in a list than an `ArrayList`. – Guillaume Polet Jun 17 '13 at 11:14
  • more than 100,00 element arre there already in list and I am adding 1 element every 20ms. 1.5 ms is average and according to my requirement it is slow. I need to insert at an particular index so I guess arraylist will be much better as for array it gives around 0.02 - 0.1 ms (I know array list need to expand and all but still) – learner Jun 17 '13 at 11:14
  • @GuillaumePolet while you are correct that insertion would not require copying of data in a `LinkedList`; finding the index `n` would be an `O(n)` operation as you have to walk the `List`. I suspect that `System.arraycopy` might have a faster constant factor and hence still be faster. – Boris the Spider Jun 17 '13 at 11:21
  • @BoristheSpider I have tried but not succeded to write code with System.array as I was not able to expand my Arraylist for proper size can you give code example on using System.arraycopy for arraylist Thanks – learner Jun 17 '13 at 11:23
  • @b.pradeep `ArrayList` already uses `System.arraycopy` internally - there is no reason for you to user it yourself. – Boris the Spider Jun 17 '13 at 11:28
  • so there isn't any way to make it faster ??? – learner Jun 17 '13 at 11:31
  • It seems like you have only given part of the requirements. You need to do a binary search to find the insert point? So this is a sorted list? Then you need a different data structure I think. Consider a TreeSet. – Steve McLeod Jun 17 '13 at 11:38
  • @BoristheSpider the `indexOf` implementation of an `ArrayList` is also `an O(n)`. See this [answer](http://stackoverflow.com/questions/322715/when-to-use-linkedlist-over-arraylist) for the full-comparison. My statement was only about add/remove operations. – Guillaume Polet Jun 17 '13 at 11:39

3 Answers3

10

If your task is more insertion / deletion intensive, you can always use java.util.LinkedList.

  • ArrayList has a limited size. Every time you add an element, Java ensures that it can fit - so it grows the ArrayList. If the ArrayList grows faster, there will be a lot of array copying taking place.
  • LinkedList just adds the element to the correct place (linking the nodes around), without growing and copying of the whole ArrayList.
  • Drawbacks of the LinkedList are when you are searching for an element. Since it has no indexes, it must traverse from the beginning to the end of the list to find an item.

For LinkedList:

  • get is O(n)
  • add is O(1)
  • remove is O(n)
  • Iterator.remove is O(1)

For ArrayList:

  • get is O(1)
  • add is O(1) amortized, but O(n) worst-case since the array must be resized and copied
  • remove is O(n)
darijan
  • 9,725
  • 25
  • 38
  • I need to first do a binary search to find index and then need to insert, I can't use Linkedlist as what I am doing is to insert in tableview which is using arraylist as underlying model (ObservableList). – learner Jun 17 '13 at 11:33
  • Can you be more specific on the TableView? – darijan Jun 17 '13 at 11:37
  • 2
    This is a copy of this [answer](http://stackoverflow.com/questions/322715/when-to-use-linkedlist-over-arraylist) (which is much more detailed) – Guillaume Polet Jun 17 '13 at 11:40
  • @GuillaumePolet +1 I have already check that answer before asking my question – learner Jun 17 '13 at 11:42
0

This insertion is happening in O(n) because it has to shift all the elements down and worst case scenario it will shift every element down. (Corrected java says it is O(n) because they use a mathematical formula to insert)

If you want a fast insertion either add it at the end of the arraylist or use a hashmap which is constant time.

Insert into hashmap: HashMap peopleMap = new Hashmap.....

peopleMap.put(person.name, person); //(or whatever you want to track)

This sets the key to th persons name and the value to person.

You can also try a hashmap with key (ehatver you want to track) and value the index where the person is in a holder array. The insert is O(i), lookup O(i) and you can sort it as well (I'll leave this as an exercise to the reader)

If the whole purpose of this is to sort, then for simplicity you could insert into a priorityQueue (nLogn) then pop everything into the array which will give you a sorted array

William Falcon
  • 9,813
  • 14
  • 67
  • 110
-2

If you add using

arryListInstance.add(positionIndex, Object);

the object will be added after sifting the existing objects by 1 position. Therefore average case of this operation become O(n).

While simple add

arryListInstance.add(positionIndex, Object);

adds the object at the end of the arrayListInstance. At it's best case this operation is O(1), but at it's worst case it becomes O(n) when the maximum capacity is reached: as a new ArrayList instance is created internally and all the contents are copied there.

You are facing this issue because one of the two reasons of which 1st can be avoided:

  1. You have not defined sufficient initial capacity for your ArrayList object. Therefore, before every arrayListInstance.add(positionIndex, object) a new arrayListInstance is being created with increased capacity and then the existing elements from the original list are being copied and then finally add is being performed. This can be avoided, if you know exactly how much data you want to handle by this list and define initial capacity accordingly (same as number of possible elments). If you cann't predict the initial capacity then it's better to process data in batches.
  2. After every insert at any position except the last causes sifting of existing elements. This is unavoidable. Therefore, arrayListInstance.add(positionIndex, object) will be performed in O(n) time if positionIndex is not the last index of the arrayList. Even if you use LinkedList you cann't achieve constant time add operation which adds an element into the list at an index other than after the last element.
Vaibhav Raj
  • 2,214
  • 4
  • 23
  • 39