Reputation: 1004
public boolean addAll(int i, Collection<? extends T> c) {
for (T x : c)
add(i++, x);
return true;
}
The List method addAll(i,c) inserts all elements of the Collection c into the list at position i. This takes a LOT of time. Is there any way it can be implemented faster ? Any ideas, please? Thanks
Here is the implementation of the arrayDeque:
public class ArrayDeque extends AbstractList { /** * The class of elements stored in this queue */ protected Factory f;
/**
* Array used to store elements
*/
protected T[] a;
/**
* Index of next element to de-queue
*/
protected int j;
/**
* Number of elements in the queue
*/
protected int n;
/**
* Grow the internal array
*/
protected void resize() {
T[] b = f.newArray(Math.max(2*n,1));
for (int k = 0; k < n; k++)
b[k] = a[(j+k) % a.length];
a = b;
j = 0;
}
/**
* Constructor
*/
public ArrayDeque(Class<T> t) {
f = new Factory<T>(t);
a = f.newArray(1);
j = 0;
n = 0;
}
public int size() {
return n;
}
public T get(int i) {
if (i < 0 || i > n-1) throw new IndexOutOfBoundsException();
return a[(j+i)%a.length];
}
public T set(int i, T x) {
if (i < 0 || i > n-1) throw new IndexOutOfBoundsException();
T y = a[(j+i)%a.length];
a[(j+i)%a.length] = x;
return y;
}
public void add(int i, T x) {
if (i < 0 || i > n) throw new IndexOutOfBoundsException();
if (n+1 > a.length) resize();
if (i < n/2) { // shift a[0],..,a[i-1] left one position
j = (j == 0) ? a.length - 1 : j - 1; // (j-1) mod a.length
for (int k = 0; k <= i-1; k++)
a[(j+k)%a.length] = a[(j+k+1)%a.length];
} else { // shift a[i],..,a[n-1] right one position
for (int k = n; k > i; k--)
a[(j+k)%a.length] = a[(j+k-1)%a.length];
}
a[(j+i)%a.length] = x;
n++;
}
public T remove(int i) {
if (i < 0 || i > n - 1) throw new IndexOutOfBoundsException();
T x = a[(j+i)%a.length];
if (i < n/2) { // shift a[0],..,[i-1] right one position
for (int k = i; k > 0; k--)
a[(j+k)%a.length] = a[(j+k-1)%a.length];
j = (j + 1) % a.length;
} else { // shift a[i+1],..,a[n-1] left one position
for (int k = i; k < n-1; k++)
a[(j+k)%a.length] = a[(j+k+1)%a.length];
}
n--;
if (3*n < a.length) resize();
return x;
}
public void clear() {
n = 0;
resize();
}
}
Upvotes: 1
Views: 323
Reputation: 372664
Rather than adding items one at a time, consider doing the following:
i
down a number of spaces equal to the number of new elements that will be added. This can be done in time O(1 + n - i), since each item is moved exactly once.Overall, this takes time O(n - i + k + 1), where n is the number of elements in the original data structure, i is the position to insert, and k is the number of new elements inserted. The key advantage is that you do all the shifting at once, rather than doing lots and lots of smaller shifts.
Hope this helps!
Upvotes: 2