从Java HashMap中提取ith值的有效方法?

时间:2016-07-26 13:44:33

标签: java performance hashmap iterator

Hello Java People,

我正在学习Java HashMaps。虽然我喜欢将它们放在一起是多么容易,但我正在考虑以有效的方式从地图中取出第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获取条目。

我已经考虑过了,我想我可以通过我的HashMap从0迭代到i:

    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

5 个答案:

答案 0 :(得分:3)

HashMap不保留插入顺序。

如果您始终希望根据索引值或其插入顺序检索数据,那么我建议使用List 实施,如ArrayList保证插入的顺序。

您可以围绕主数据对象创建一个包装器对象并将它们放在ArrayList中,当您需要读取它时,可以使用您想要读取的索引值使用get方法

答案 1 :(得分:2)

HashMap不打算以这种方式使用,因为不保证条目的顺序。如果您确实需要key-&gt;值结构,则最好使用ArrayListLinkedHashMap

答案 2 :(得分:2)

没有有效方法从HashMap中提取第i个条目。实际上,来自HashMap的第i个条目甚至不是一个明确定义的概念,因为HashMap中条目的排序未指定。

(相比之下,LinkedHashMap的条目可以按照插入条目的顺序进行迭代。但即使对于LinkedHashMap,也无法对#34;索引&#34;除了从开始迭代之外的条目,这是O(I)操作,其中I是您尝试检索的元素的索引。)

底线:如果您希望使用索引进行有效(即O(1))查找,则应使用ArrayList或基本数组。

(或者,也许,使用索引值作为哈希表的键,或者使用主哈希表中条目的单独哈希表。但是,你要谈的是更复杂的数据结构和/或不同的模型&#34;索引&#34;。)

答案 3 :(得分:1)

如果你不知道密钥,那么HashMap就没用了! 改为使用ArrayList或类似的东西。

如果您的HashMap确实非常非常大(即它不适合您的可用内存),那么您可以考虑使用以下内容: http://www.oracle.com/technetwork/database/berkeleydb/overview/index-093405.html

答案 4 :(得分:1)

作为名称,&#34; 哈希地图,&#34;暗示,底层数据结构是一个&#34;哈希表。&#34;从概念上讲,它是一系列&#34;桶,&#34;关键是&#34;哈希&#34;确定要查看哪个(一个)存储桶以尝试查找该密钥。这是一个非常有效的数据结构,用于按值查找键,但它没有&#34; order的概念。&#34;

Java拥有非常丰富的数据结构选择:各种树,集合等等。即便是好的&#39; 数组!您需要选择更适合您需求的其他结构。

(并且请记住,某些东西可能是&#34;在......中......也就是说,&#34;&#34; ......一次只有一个这样的容器,与SQL表可能具有多个索引的方式大致相同。)