Java Hashmap 与数组性能

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/6462055/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-16 06:09:25  来源:igfitidea点击:

Hashmap vs Array performance

javaarraysperformanceoptimizationhashmap

提问by Timotheus

Is it (performance-wise) better to use Arrays or HashMaps when the indexes of the Array are known? Keep in mind that the 'objects array/map' in the example is just an example, in my real project it is generated by another class so I cant use individual variables.

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

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
}

The HashMap one looks much much better but I really need performance on this so that has priority.

HashMap 看起来好多了,但我真的需要在这方面的性能,以便优先考虑。

EDIT:Well Array's it is then, suggestions are still welcome

编辑:那么阵列就是这样,仍然欢迎建议

EDIT:I forgot to mention, the size of the Array/HashMap is always the same (6)

编辑:我忘了提到,数组/HashMap 的大小总是相同的 (6)

EDIT:It appears that HashMaps are faster Array: 128ms Hash: 103ms

编辑:HashMaps 似乎更快 Array: 128ms Hash: 103ms

When using less cycles the HashMaps was even twice as fast

当使用更少的周期时,HashMaps 的速度甚至是原来的两倍

test code:

测试代码:

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();
}

}

}

采纳答案by Peter Lawrey

HashMap uses an array underneath so it can never be faster than using an array correctly.

HashMap 在底层使用数组,因此它永远不会比正确使用数组更快。

Random.nextInt()is many times slower than what you are testing, even using array to test an array is going to bias your results.

Random.nextInt()比您正在测试的速度慢很多倍,即使使用数组来测试数组也会使您的结果产生偏差。

The reason your array benchmark is so slow is due to the equals comparisons, not the array access itself.

您的数组基准测试如此缓慢的原因是由于相等比较,而不是数组访问本身。

HashTableis usually much slower than HashMapbecause it does much the same thing but is also synchronized.

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

A common problem with micro-benchmarks is the JIT which is very good at removing code which doesn't do anything. If you are not careful you will only be testing whether you have confused the JIT enough that it cannot workout your code doesn't do anything.

微基准测试的一个常见问题是 JIT,它非常擅长删除不做任何事情的代码。如果您不小心,您将只会测试您是否已经将 JIT 弄糊涂了,以至于它无法锻炼您的代码并没有做任何事情。

This is one of the reason you can write micro-benchmarks which out perform C++ systems. This is because Java is a simpler language and easier to reason about and thus detect code which does nothing useful. This can lead to tests which show that Java does "nothing useful" much faster than C++ ;)

这是您可以编写超越 C++ 系统的微基准测试的原因之一。这是因为 Java 是一种更简单的语言,更容易推理并因此检测没有任何用处的代码。这可能导致测试表明 Java“没有任何用处”比 C++ 快得多;)

回答by ratchet freak

arrays when the indexes are know are faster (HashMap uses an array of linked lists behind the scenes which adds a bit of overhead above the array accesses not to mention the hashing operations that need to be done)

知道索引时的数组更快(HashMap 在幕后使用了一个链表数组,这在数组访问之上增加了一点开销,更不用说需要完成的散列操作)

and FYI HashMap<String,SomeObject> objects = HashMap<String,SomeObject>();makes it so you won't have to cast

仅供参考HashMap<String,SomeObject> objects = HashMap<String,SomeObject>();,这样你就不必投射了

回答by sehe

For the example shown, HashTable wins, I believe. The problem with the array approach is that it doesn't scale. I imagine you want to have more than two entries in the table, and the condition branch tree in doSomethingToObject will quickly get unwieldly and slow.

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

回答by Basanth Roy

Arrays will usually be faster than Collections classes.

数组通常比集合类更快。

PS. You mentioned HashTable in your post. HashTable has even worse performance thatn HashMap. I assume your mention of HashTable was a typo

附注。您在帖子中提到了 HashTable。HashTable 的性能甚至比 HashMap 还要差。我认为你提到的 HashTable 是一个错字

"The HashTable one looks much much better "

“HashTable 看起来好多了”

回答by Alex Gitelman

Logically, HashMapis definitely a fit in your case. From performance standpoint is also wins since in case of arrays you will need to do number of string comparisons (in your algorithm) while in HashMap you just use a hash code if load factor is not too high. Both array and HashMap will need to be resized if you add many elements, but in case of HashMap you will need to also redistribute elements. In this use case HashMap loses.

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

回答by BlueGuitar

The example is strange. The key problem is whether your data is dynamic. If it is, you could not write you program that way (as in the array case). In order words, comparing between your array and hash implementation is not fair. The hash implementation works for dynamic data, but the array implementation does not.

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

If you only have static data (6 fixed objects), array or hash just work as data holder. You could even define static objects.

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

回答by Ajax

Please, never, ever use extended if / else if / else if / else if / else if / else if cases like that. The reason I repeated it so many times is just to make you feel like your java interpreter does when it hits code-blocks like that.

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

As soon as you have more than one else if, either use a hashmap, or a switch / case (java 7 will let you do it on Strings, and java 6 you have to use an enum). An even better solution for read-only checking is an ImmutableMap from a framework like guava; they have highly optimized reads as they don't allow writes.

一旦你有多个 if,要么使用 hashmap,要么使用 switch/case(java 7 会让你在字符串上做,而 java 6 你必须使用枚举)。一个更好的只读检查解决方案是来自 Guava 等框架的 ImmutableMap;它们具有高度优化的读取,因为它们不允许写入。