Hashmap与阵列性能

时间:2011-06-24 00:13:43

标签: java arrays performance optimization hashmap

当已知Array的索引时,使用Arrays或HashMaps是否(性能方面)更好?请记住,示例中的'objects array / map'只是一个示例,在我的实际项目中它由另一个类生成,因此我无法使用单个变量。

ArrayExample:

SomeObject[] objects = new SomeObject[2];
objects[0] = new SomeObject("Obj1");
objects[1] = new SomeObject("Obj2");

void doSomethingToObject(String Identifier){
    SomeObject object;
    if(Identifier.equals("Obj1")){
        object=objects[0];
    }else if(){
        object=objects[1];
    }
    //do stuff
}

HashMapExample:

HashMap objects = HashMap();
objects.put("Obj1",new SomeObject());
objects.put("Obj2",new SomeObject());

void doSomethingToObject(String Identifier){
    SomeObject object = (SomeObject) objects.get(Identifier);
    //do stuff
}

HashMap看起来要好得多,但我真的需要这方面的表现才能优先考虑。

编辑: Well Array就是这样,仍然欢迎提出建议

编辑:我忘了提一下,Array / HashMap的大小总是一样的(6)

编辑:看起来HashMaps速度更快 阵列:128ms 哈希:103毫秒

当使用较少的周期时,HashMaps甚至快了两倍

测试代码:

import java.util.HashMap;
import java.util.Random;

public class Optimizationsest {
private static Random r = new Random();

private static HashMap<String,SomeObject> hm = new HashMap<String,SomeObject>();
private static SomeObject[] o = new SomeObject[6];

private static String[] Indentifiers = {"Obj1","Obj2","Obj3","Obj4","Obj5","Obj6"};

private static int t = 1000000;

public static void main(String[] args){
    CreateHash();
    CreateArray();
    long loopTime = ProcessArray();
    long hashTime = ProcessHash();
    System.out.println("Array: " + loopTime + "ms");
    System.out.println("Hash: " + hashTime + "ms");
}

public static void CreateHash(){
    for(int i=0; i <= 5; i++){
        hm.put("Obj"+(i+1), new SomeObject());
    }
}

public static void CreateArray(){
    for(int i=0; i <= 5; i++){
        o[i]=new SomeObject();
    }
}

public static long ProcessArray(){
    StopWatch sw = new StopWatch();
    sw.start();
    for(int i = 1;i<=t;i++){
        checkArray(Indentifiers[r.nextInt(6)]);
    }
    sw.stop();
    return sw.getElapsedTime();
}



private static void checkArray(String Identifier) {
    SomeObject object;
    if(Identifier.equals("Obj1")){
        object=o[0];
    }else if(Identifier.equals("Obj2")){
        object=o[1];
    }else if(Identifier.equals("Obj3")){
        object=o[2];
    }else if(Identifier.equals("Obj4")){
        object=o[3];
    }else if(Identifier.equals("Obj5")){
        object=o[4];
    }else if(Identifier.equals("Obj6")){
        object=o[5];
    }else{
        object = new SomeObject();
    }
    object.kill();
}

public static long ProcessHash(){
    StopWatch sw = new StopWatch();
    sw.start();
    for(int i = 1;i<=t;i++){
        checkHash(Indentifiers[r.nextInt(6)]);
    }
    sw.stop();
    return sw.getElapsedTime();
}

private static void checkHash(String Identifier) {
    SomeObject object = (SomeObject) hm.get(Identifier);
    object.kill();
}

}

7 个答案:

答案 0 :(得分:32)

HashMap使用下面的数组,因此它永远不会比正确使用数组更快。

Random.nextInt()比您测试的慢很多倍,即使使用数组测试数组也会偏向您的结果。

您的阵列基准测试速度如此之慢的原因是由于等于比较,而不是数组访问本身。

HashTable通常比HashMap慢得多,因为它做了很多相同的事情,但也是同步的。

微基准测试的一个常见问题是JIT非常擅长删除无法执行任何操作的代码。如果你不小心,你只会测试你是否已经混淆了JIT,以至于它无法锻炼你的代码什么都不做。

这是您可以编写执行C ++系统的微基准测试的原因之一。这是因为Java是一种更简单的语言,更易于推理,从而检测出无用的代码。这可以导致测试表明Java“没有用”比C ++快得多;)

答案 1 :(得分:4)

知道索引时的

数组更快(HashMap在幕后使用链接列表数组,这会在数组访问之上增加一些开销,更不用说需要完成的散列操作了)

和FYI HashMap<String,SomeObject> objects = HashMap<String,SomeObject>();使你无需投射

答案 2 :(得分:2)

对于所示示例,HashTable获胜,我相信。阵列方法的问题在于它不能扩展。我想你想在表中有两个以上的条目,并且doSomethingToObject中的条件分支树将很快变得笨拙和缓慢。

答案 3 :(得分:2)

逻辑上,HashMap绝对适合您的情况。从性能角度来看也是胜利,因为在数组的情况下,您需要进行多次字符串比较(在您的算法中),而在HashMap中,如果加载因子不是太高,您只需使用哈希码。如果添加许多元素,则需要调整数组和HashMap的大小,但是在HashMap的情况下,您还需要重新分配元素。在这个用例中,HashMap失败了。

答案 4 :(得分:0)

数组通常比集合类快。

PS。你在帖子中提到了HashTable。 HashTable的性能甚至比HashMap差。我假设你提到HashTable是一个错字

  

“HashTable看起来很多   更好“

答案 5 :(得分:0)

这个例子很奇怪。关键问题是您的数据是否是动态的。如果是,你不能用这种方式编写程序(如在数组的情况下)。换句话说,比较你的数组和哈希实现是不公平的。哈希实现适用于动态数据,但数组实现不适用。

如果您只有静态数据(6个固定对象),则数组或散列仅用作数据持有者。你甚至可以定义静态对象。

答案 6 :(得分:0)

请永远不要使用扩展if / else如果/ else if / else if / else if / else if / else if case。我重复这么多次的原因只是为了让你觉得你的java解释器在遇到像这样的代码块时会这样做。

如果你有多个其他的,无论是使用hashmap还是switch / case(java 7将允许你在Strings上执行,而java 6则必须使用枚举)。用于只读检查的更好的解决方案是来自像番石榴这样的框架的ImmutableMap;它们具有高度优化的读取,因为它们不允许写入。