【发布时间】:2016-11-30 04:53:44
【问题描述】:
Java 人你好,
我正在学习 Java HashMap。虽然我喜欢将它们放在一起是多么容易,但我正在考虑以一种有效的方式从地图中提取第 i 个条目。解释...
假设这是我的代码:
package HashPackage;
import java.util.HashMap;
public class newHashObject {
// Nested class
public class newObject {
int Data1;
int Data2;
public newObject(int a, int b){
this.Data1 = a;
this.Data2 = b;
}
}
// HashMap to contain newObjects
HashMap<Integer, newObject> cache = new HashMap<Integer, newObject>();
// Constructor
public newHashObject(){
// populate cache with 1000 newObjects:
for(int i=0; i<1000; i++)
cache.put(i, new newObject(i, i*2+101));
System.out.println("New cache created, total objects in cache: "+cache.size());
}
}
好的,到目前为止还没有什么激进的。在现实生活中,我的 HashMap 中的条目不会使用等于 0、1、2、3 等的键来归档,而是会使用本质上是随机数的键来归档。即,如果您要检查我的“现实生活”HashMap,您会看到键为 19、79、235、577、1023、1092 等的条目。
现在假设我需要从 HashMap 中准确提取第 i 个元素。我不会提前知道键值。例如,使用上面的“现实生活”地图:如果我们开始用 0 对地图的条目进行编号,并且我想取出第 i=4 个条目,那么我应该得到键为 1023 的条目。
我已经考虑过了,我想我可以从 0 到 i 遍历我的 HashMap:
import java.util.Iterator;
...
// Is there a better way to do this?
public newObject iterateByIndex(int index){
Iterator<Integer> keySetIterator = cache.keySet().iterator();
int count=0;
if(index<cache.size()){
while(keySetIterator.hasNext()){
Integer key = keySetIterator.next();
if(count==index){
// We've found the ith entry in the cache
return cache.get(key);
}
count++;
}
}
return null;
}
这段代码有效,但看起来很笨拙,而且效率肯定很低。我可能需要调用此方法数百万次(不撒谎!),并且每次从 0 迭代到 i 将耗费大量时间。
那么……有什么建议吗? HashMap 在这里是错误的数据结构吗? (我使用 HashMap 是因为我的数据集非常非常大。)我很好奇经验丰富的程序员在这种情况下会做什么。
感谢您的任何建议, -P
【问题讨论】:
-
如果您需要在 HashMap 中的“ith”元素处引用某些内容,则说明您使用了错误的数据结构。
-
HashMap没有定义的顺序,所以“i-th”不是一个定义的概念。 “这个类不保证地图的顺序;特别是,它不保证顺序会随着时间的推移保持不变。” -
具体来说,地图接口不传达任何排序。有一些 Map 的实现是有序的,例如 TreeMap 和 LinkedHashMap。你可以看看那些。 (但应该注意,这些仅授予“可预测的迭代顺序” - 您不能只要求第 425 个条目而不迭代第一个 424。不理想!)
-
@AndyTurner 我同意,即使是一个已排序映射的
TreeMap,也不一定公开对索引的访问。
标签: java performance hashmap iterator