Reputation: 359
I have multiple ArrayList
s with lots of data and I need to manipulate the data quickly and efficiently. My code currently makes a duplicate of the original ArrayList
so that I can make changes (avoiding ConcurrentModificationException
). This approach seems somewhat inefficient.
I've looked into ListIterator
s and they seem much more "clean" and efficient. I ran a quick test to see which is actually faster and it seems duplicating the original ArrayList
may be faster. Is this true or is my test flawed in some way? If it is true, does it only hold for smaller ArrayList
s?
The test I ran is below:
long startTime, stopTime;
ArrayList<ArrayList<String>> array = new ArrayList<>();
ArrayList<String> a1 = new ArrayList<>();
ArrayList<String> a2 = new ArrayList<>();
ArrayList<String> a3 = new ArrayList<>();
for (int i = 0; i < 5; i++) {
a1.add(Integer.toString(i));
a2.add(Integer.toString(i));
a3.add(Integer.toString(i));
}
array.add(a1);
array.add(a2);
array.add(a3);
startTime = System.nanoTime();
ArrayList<ArrayList<String>> arrayCopy = new ArrayList<>();
for (int i = 0; i < array.size(); i++) {
ArrayList<String> line = array.get(i);
arrayCopy.add(i, new ArrayList<>(line.size()));
for (int j = 0; j < line.size(); j++) {
arrayCopy.get(i).add(j, line.get(j));
}
}
for (int j = 0; j < array.size(); j++) {
for (int i = 0; i < array.get(j).size(); i++) {
if (array.get(j).get(i).equals("2")) {
arrayCopy.get(j).add(i, "1.5");
}
}
}
stopTime = System.nanoTime() - startTime;
System.out.println(arrayCopy.get(0));
System.out.println(arrayCopy.get(1));
System.out.println(arrayCopy.get(2));
System.out.println(stopTime);
ArrayList<ArrayList<String>> brray = new ArrayList<>();
ArrayList<String> b1 = new ArrayList<>();
ArrayList<String> b2 = new ArrayList<>();
ArrayList<String> b3 = new ArrayList<>();
for (int i = 0; i < 5; i++) {
b1.add(Integer.toString(i));
b2.add(Integer.toString(i));
b3.add(Integer.toString(i));
}
brray.add(b1);
brray.add(b2);
brray.add(b3);
startTime = System.nanoTime();
for (ArrayList<String> s : brray) {
ListIterator<String> i = s.listIterator();
while (i.hasNext()) {
if (i.next().equals("1")) {
i.add("1.5");
}
}
}
stopTime = System.nanoTime() - startTime;
System.out.println(b1);
System.out.println(b2);
System.out.println(b3);
System.out.println(stopTime);
Running the code five times gave me times (in nano seconds) of 73307, 46916, 77705, 76606 and 82470
for the duplicating method and 307888, 319984, 304590, 363235 and 280032
for the ListIterator
method.
Upvotes: 1
Views: 96
Reputation: 1603
Take a look in to ArrayList implementation. http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.add%28java.lang.Object%29
You need much more items to make a good test. The ArrayList uses array inside and creates by default an array of 10 item. So your add/get etc. methodes have a complexity of O(1). You can look into listIterator method. It use the same approach. I guess, you don't need to use iterator when you use ArrayList explicitly but when you use List interface, because the implementation can be different.
Upvotes: 0
Reputation: 313
I'm not sure without looking at their implementation but from some tests:
For larger sizes, ListIterator will beat out ArrayList method.
For smaller sizes, just creating the ListIterator takes longer than the ArrayList method.
Also, time benchmarks are kind of questionable, because there is a lot more to it than just the program itself. Especially those in the 10^(-3) seconds.
Upvotes: 1