【发布时间】:2012-10-10 17:20:52
【问题描述】:
我一直在用一堆不同的方法来搜索集合、集合集合等。做了很多愚蠢的小测试来验证我的理解。这是一个让我感到困惑的(源代码在下面)。
简而言之,我正在生成 N 个随机整数并将它们添加到列表中。该列表未排序。然后我使用Collections.contains() 在列表中查找一个值。我有意寻找一个我知道不会存在的值,因为我想确保探测到整个列表空间。我为这个搜索计时。
然后我手动进行另一个线性搜索,遍历列表的每个元素并检查它是否与我的目标匹配。我也为这个搜索计时。
平均而言,第二次搜索的时间比第一次长 33%。按照我的逻辑,第一次搜索也必须是线性的,因为列表是未排序的。我能想到的唯一可能性(我立即放弃)是 Java 正在制作我的列表的排序副本只是为了搜索,但是(1)我没有授权使用内存空间和(2)我认为使用如此大的 N 会节省更多时间。
因此,如果两个搜索都是线性的,则它们应该花费相同的时间。 Collections 类以某种方式优化了此搜索,但我不知道如何。那么……我错过了什么?
import java.util.*;
public class ListSearch {
public static void main(String[] args) {
int N = 10000000; // number of ints to add to the list
int high = 100; // upper limit for random int generation
List<Integer> ints;
int target = -1; // target will not be found, forces search of entire list space
long start;
long end;
ints = new ArrayList<Integer>();
start = System.currentTimeMillis();
System.out.print("Generating new list... ");
for (int i = 0; i < N; i++) {
ints.add(((int) (Math.random() * high)) + 1);
}
end = System.currentTimeMillis();
System.out.println("took " + (end-start) + "ms.");
start = System.currentTimeMillis();
System.out.print("Searching list for target (method 1)... ");
if (ints.contains(target)) {
// nothing
}
end = System.currentTimeMillis();
System.out.println(" Took " + (end-start) + "ms.");
System.out.println();
ints = new ArrayList<Integer>();
start = System.currentTimeMillis();
System.out.print("Generating new list... ");
for (int i = 0; i < N; i++) {
ints.add(((int) (Math.random() * high)) + 1);
}
end = System.currentTimeMillis();
System.out.println("took " + (end-start) + "ms.");
start = System.currentTimeMillis();
System.out.print("Searching list for target (method 2)... ");
for (Integer i : ints) {
// nothing
}
end = System.currentTimeMillis();
System.out.println(" Took " + (end-start) + "ms.");
}
}
编辑:以下是此代码的新版本。有趣的是,现在我的手动线性循环比contains 方法执行了 16% faster(注意:两者都旨在有意搜索整个列表空间,所以我知道它们的数量相等迭代)。我无法解释这 16% 的收益……更多的困惑。
import java.util.*;
public class ListSearch {
public static void main(String[] args) {
int N = 10000000; // number of ints to add to the list
int high = 100; // upper limit for random int generation
List<Integer> ints;
int target = -1; // target will not be found, forces search of entire list space
long start;
long end;
ints = new ArrayList<Integer>();
start = System.currentTimeMillis();
System.out.print("Generating new list... ");
for (int i = 0; i < N; i++) {
ints.add(((int) (Math.random() * high)) + 1);
}
end = System.currentTimeMillis();
System.out.println("took " + (end-start) + "ms.");
start = System.currentTimeMillis();
System.out.print("Searching list for target (method 1)... ");
if (ints.contains(target)) {
System.out.println("hit");
}
end = System.currentTimeMillis();
System.out.println(" Took " + (end-start) + "ms.");
System.out.println();
ints = new ArrayList<Integer>();
start = System.currentTimeMillis();
System.out.print("Generating new list... ");
for (int i = 0; i < N; i++) {
ints.add(((int) (Math.random() * high)) + 1);
}
end = System.currentTimeMillis();
System.out.println("took " + (end-start) + "ms.");
start = System.currentTimeMillis();
System.out.print("Searching list for target (method 2)... ");
for (int i = 0; i < N; i++) {
if (ints.get(i) == target) {
System.out.println("hit");
}
}
end = System.currentTimeMillis();
System.out.println(" Took " + (end-start) + "ms.");
}
}
【问题讨论】:
-
您是否意识到您的第二个“搜索”甚至不是搜索?它只是迭代列表的元素...
-
是的,实际上我几分钟前才意识到这一点,现在我正在更多地使用我的代码。对于那个很抱歉。可能需要尽快运行,但稍后会更新此帖子。
标签: java collections linear-search