我曾认为HashMap对单个值的随机访问比ArrayLists更快。。。也就是说,HashMap.get(key)应该比ArrayList.get(index)更快,因为ArrayList必须遍历集合的每个元素才能达到它的值,而HashMap没有。你知道,O(1)和O(n)等等。
编辑:,所以我对HashMap的理解不够充分,因此我很困惑。此代码的结果与预期的相同。谢谢你这么多解释。
所以我决定在云雀上测试它。这是我的代码:
import java.util.HashMap;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.NoSuchElementException;
import java.util.Scanner;
public class Testing
{
public static void main(String[] args)
{
ArrayList<SomeClass> alist = new ArrayList<>();
HashMap<Short, SomeClass> hmap = new HashMap<>(4000, (float).75);
ListIterator<SomeClass> alistiterator = alist.listIterator();
short j = 0;
do
{
alistiterator.add(new SomeClass());
j++;
}
while(j < 4000);
for (short i = 0; i < 4000; i++)
{
hmap.put(i, new SomeClass());
}
boolean done = false;
Scanner input = new Scanner(System.in);
String blargh = null;
do
{
System.out.println("\nEnter 1 to run iteration tests.");
System.out.println("Enter w to run warmup (recommended)");
System.out.println("Enter x to terminate program.");
try
{
blargh = input.nextLine();
}
catch (NoSuchElementException e)
{
System.out.println("Uh, what? Try again./n");
continue;
}
switch (blargh)
{
case "1":
long starttime = 0;
long total = 0;
for (short i = 0; i < 1000; i++)
{
starttime = System.nanoTime();
iteratearraylist(alist);
total += System.nanoTime() - starttime;
}
total = (long)(total * .001);
System.out.println(total + " ns: iterating sequentially"
+ " through ArrayList");
total = 0;
for (short i = 0; i< 1000; i++)
{
starttime = System.nanoTime();
iteratearraylistbyget(alist);
total += System.nanoTime() - starttime;
}
total = (long)(total * .001);
System.out.println(total + " ns: iterating sequentially"
+ " through ArrayList via .get()");
total = 0;
for (short i = 0; i< 1000; i++)
{
starttime = System.nanoTime();
iteratehashmap(hmap);
total += System.nanoTime() - starttime;
}
total = (long)(total * .001);
System.out.println(total + " ns: iterating sequentially"
+ " through HashMap via .next()");
total = 0;
for (short i = 0; i< 1000; i++)
{
starttime = System.nanoTime();
iteratehashmapbykey(hmap);
total += System.nanoTime() - starttime;
}
total = (long)(total * .001);
System.out.println(total + " ns: iterating sequentially"
+ " through HashMap via .get()");
total = 0;
for (short i = 0; i< 1000; i++)
{
starttime = System.nanoTime();
getvaluebyindex(alist);
total += System.nanoTime() - starttime;
}
total = (long)(total * .001);
System.out.println(total + " ns: getting end value"
+ " from ArrayList");
total = 0;
for (short i = 0; i< 1000; i++)
{
starttime = System.nanoTime();
getvaluebykey(hmap);
total += System.nanoTime() - starttime;
}
total = (long)(total * .001);
System.out.println(total + " ns: getting end value"
+ " from HashMap");
break;
case "w":
for (int i = 0; i < 60000; i++)
{
iteratearraylist(alist);
iteratearraylistbyget(alist);
iteratehashmap(hmap);
iteratehashmapbykey(hmap);
getvaluebyindex(alist);
getvaluebykey(hmap);
}
break;
case "x":
done = true;
break;
default:
System.out.println("Invalid entry. Please try again.");
break;
}
}
while (!done);
input.close();
}
public static void iteratearraylist(ArrayList<SomeClass> alist)
{
ListIterator<SomeClass> tempiterator = alist.listIterator();
do
{
tempiterator.next();
}
while (tempiterator.hasNext());
}
public static void iteratearraylistbyget(ArrayList<SomeClass> alist)
{
short i = 0;
do
{
alist.get(i);
i++;
}
while (i < 4000);
}
public static void iteratehashmap(HashMap<Short, SomeClass> hmap)
{
Iterator<HashMap.Entry<Short, SomeClass>> hmapiterator =
map.entrySet().iterator();
do
{
hmapiterator.next();
}
while (hmapiterator.hasNext());
}
public static void iteratehashmapbykey(HashMap<Short, SomeClass> hmap)
{
short i = 0;
do
{
hmap.get(i);
i++;
}
while (i < 4000);
}
public static void getvaluebykey(HashMap<Short, SomeClass> hmap)
{
hmap.get(3999);
}
public static void getvaluebyindex(ArrayList<SomeClass> alist)
{
alist.get(3999);
}
}和
public class SomeClass
{
int a = 0;
float b = 0;
short c = 0;
public SomeClass()
{
a = (int)(Math.random() * 100000) + 1;
b = (float)(Math.random() * 100000) + 1.0f;
c = (short)((Math.random() * 32000) + 1);
}
}有趣的是,代码似乎是分阶段升温的。我所确定的最后阶段是在对所有方法进行了大约12万次迭代之后。无论如何,在我的测试机器(AMDx2-220,L3 +1额外的核心解锁,3.6GHz,2.1GHz NB)上,真正跳出我的数字是最后两个报告。即,.get()的时间-- ArrayList (index == 3999)的最后一个条目,以及与3999的短键相关联的值到.get()的时间。
经过2-3个热身周期后,测试表明ArrayList.get()大约需要56 ns,而HashMap.get()大约需要68 ns.就是这样。。。可不是我期望的。我的HashMap是不是都被碰撞吞噬了?所有的键条目都应该自动设置为短片,这应该是为了响应.hashcode()来报告它们存储的短值,所以所有的哈希码都应该是唯一的。我认为?
即使没有战争,ArrayList.get()仍然更快。这与我在其他地方看到的所有东西都不一样,比如this question。当然,我也读过用ArrayList遍历ListIterator比在循环中使用.get()更快,显然也不是这样。。。
发布于 2014-11-07 21:46:42
Hashmap无法在已知索引下更快地检索某些内容。如果您以已知的顺序存储东西,列表将获胜。
但是,假设不是将所有内容插入列表1-4000中的例子,而是以完全随机的顺序进行的。现在,要从列表中检索正确的项目,您必须逐一检查每个项目,寻找正确的项目。但是要从hashmap检索它,您只需要知道插入它时应该给它的键。
所以,实际上,您应该将Hashmap.get(i)与
for(Integer i : integerList)
if(i==value)
//found it!然后您将看到hashmap的真正效率。
发布于 2014-11-07 20:32:19
ArrayList必须遍历集合的每个元素才能达到它的值。
这不是真的。ArrayList由一个允许固定时间get操作的数组支持.
另一方面,HashMap的get首先必须散列它的参数,然后它必须遍历哈希代码对应的桶,测试桶中的每个元素是否与给定的键相等。这通常比索引数组要慢。
发布于 2014-11-07 20:29:37
ArrayList.get(index)通常使用恒定的时间,因为ArrayList是由数组支持的,所以它只在bacing数组中使用该索引。在最坏的情况下,ArrayList.contains(Object)是O(n)的长期操作。
https://stackoverflow.com/questions/26809537
复制相似问题