尝试操作 ArrayList 时复制 ArrayList 或使用 ListIterator 是否更快?
Is duplicating an ArrayList or using a ListIterator faster when trying to manipulate an ArrayList?
我有多个 ArrayList
,其中包含大量数据,我需要快速高效地处理数据。我的代码目前复制了原始 ArrayList
,以便我可以进行更改(避免 ConcurrentModificationException
)。这种方法似乎有些低效。
我调查了 ListIterator
s,它们似乎 "clean" 更有效。我 运行 进行了快速测试,看看哪个实际上更快,似乎复制原始 ArrayList
可能更快。这是真的还是我的测试在某种程度上存在缺陷?如果是真的,它只适用于较小的 ArrayList
s 吗?
我运行的测试如下:
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);
运行 代码五次为复制方法提供了 73307, 46916, 77705, 76606 and 82470
的时间(以纳秒为单位),为 ListIterator
方法提供了 307888, 319984, 304590, 363235 and 280032
的时间。
我不确定不看他们的实施,但从一些测试来看:
对于更大的尺寸,ListIterator 将击败 ArrayList 方法。
对于较小的尺寸,仅创建 ListIterator 比 ArrayList 方法花费的时间更长。
此外,时间基准有点值得怀疑,因为它不仅仅是程序本身。尤其是在 10^(-3) 秒内。
查看 ArrayList 实现。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.add%28java.lang.Object%29
您需要更多的项目才能进行良好的测试。 ArrayList 在内部使用数组并默认创建一个包含 10 个项目的数组。所以你的 add/get 等方法的复杂度为 O(1)。您可以查看 listIterator 方法。它使用相同的方法。我想,显式使用 ArrayList 时不需要使用迭代器,但使用 List 接口时,因为实现可能不同。
我有多个 ArrayList
,其中包含大量数据,我需要快速高效地处理数据。我的代码目前复制了原始 ArrayList
,以便我可以进行更改(避免 ConcurrentModificationException
)。这种方法似乎有些低效。
我调查了 ListIterator
s,它们似乎 "clean" 更有效。我 运行 进行了快速测试,看看哪个实际上更快,似乎复制原始 ArrayList
可能更快。这是真的还是我的测试在某种程度上存在缺陷?如果是真的,它只适用于较小的 ArrayList
s 吗?
我运行的测试如下:
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);
运行 代码五次为复制方法提供了 73307, 46916, 77705, 76606 and 82470
的时间(以纳秒为单位),为 ListIterator
方法提供了 307888, 319984, 304590, 363235 and 280032
的时间。
我不确定不看他们的实施,但从一些测试来看:
对于更大的尺寸,ListIterator 将击败 ArrayList 方法。
对于较小的尺寸,仅创建 ListIterator 比 ArrayList 方法花费的时间更长。
此外,时间基准有点值得怀疑,因为它不仅仅是程序本身。尤其是在 10^(-3) 秒内。
查看 ArrayList 实现。 http://grepcode.com/file/repository.grepcode.com/java/root/jdk/openjdk/6-b14/java/util/ArrayList.java#ArrayList.add%28java.lang.Object%29
您需要更多的项目才能进行良好的测试。 ArrayList 在内部使用数组并默认创建一个包含 10 个项目的数组。所以你的 add/get 等方法的复杂度为 O(1)。您可以查看 listIterator 方法。它使用相同的方法。我想,显式使用 ArrayList 时不需要使用迭代器,但使用 List 接口时,因为实现可能不同。