哈希图与数组性能
当数组的索引已知时,使用数组或 HashMap 是否(性能方面)更好?请记住,示例中的“对象数组/映射”只是一个示例,在我的实际项目中,它是由另一个类生成的,因此我不能使用单独的变量。
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 看起来好多了,但我确实需要这方面的性能,以便优先考虑。
编辑: 那么数组就是这样,仍然欢迎提出建议
编辑: 我忘了提及,Array/HashMap 的大小始终相同 (6)
编辑: 看来 HashMap 更快 阵列:128ms 哈希:103 毫秒
当使用更少的周期时,HashMap 的速度甚至是测试代码的两倍
:
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();
}
}
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.
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.
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)
EDIT: It appears that HashMaps are faster
Array: 128ms
Hash: 103ms
When using less cycles the HashMaps was even twice as fast
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();
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(7)
HashMap 在底层使用数组,因此它永远不会比正确使用数组更快。
Random.nextInt()
比您正在测试的慢很多倍,即使使用数组来测试数组也会使您的结果产生偏差。数组基准测试如此慢的原因是由于 equals 比较,而不是数组访问本身。
HashTable
通常比HashMap
慢得多,因为它做的事情大致相同,但也是同步的。微基准的一个常见问题是 JIT,它非常擅长删除不执行任何操作的代码。如果你不小心,你只会测试你是否对 JIT 感到困惑,以至于它无法锻炼你的代码,不会做任何事情。
这是您可以编写性能优于 C++ 系统的微基准的原因之一。这是因为 Java 是一种更简单的语言,更容易推理,从而检测出没有任何用处的代码。这可能会导致测试表明 Java 比 C++ 更快地“没有做任何有用的事情”;)
HashMap uses an array underneath so it can never be faster than using an array correctly.
Random.nextInt()
is many times slower than what you are testing, even using array to test an array is going to bias your results.The reason your array benchmark is so slow is due to the equals comparisons, not the array access itself.
HashTable
is usually much slower thanHashMap
because it does much the same thing but is also synchronized.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.
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++ ;)
当索引已知时,数组速度更快(HashMap 在幕后使用链表数组,这在数组访问之上增加了一些开销,更不用说需要完成的哈希操作)
并且仅供参考
HashMapobjects = HashMap();
使得您不必进行强制转换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)
and FYI
HashMap<String,SomeObject> objects = HashMap<String,SomeObject>();
makes it so you won't have to cast对于所示的示例,我相信 HashTable 获胜。数组方法的问题是它无法扩展。我想您希望表中有两个以上的条目,并且 doSomethingToObject 中的条件分支树很快就会变得笨拙且缓慢。
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.
从逻辑上讲,
HashMap
绝对适合您的情况。从性能的角度来看,这也是胜利,因为在数组的情况下,您将需要进行多次字符串比较(在您的算法中),而在 HashMap 中,如果负载因子不太高,您只需使用哈希码。如果添加许多元素,数组和 HashMap 都需要调整大小,但对于 HashMap,您还需要重新分配元素。在这个用例中,HashMap 失败了。Logically,
HashMap
is 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.数组通常比集合类更快。
附言。您在帖子中提到了哈希表。 HashTable 的性能比 HashMap 还要差。我认为你提到的 HashTable 是一个拼写错误
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
这个例子很奇怪。关键问题是你的数据是否是动态的。如果是,您就无法以这种方式编写程序(如数组情况)。换句话说,比较数组和哈希实现是不公平的。哈希实现适用于动态数据,但数组实现则不然。
如果您只有静态数据(6 个固定对象),则数组或哈希只是作为数据持有者。您甚至可以定义静态对象。
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.
我想知道没有人谈论 Hashmap 的性能。不要忘记这样一个事实:每次将数据放入 Hashmap 并在后台从 hashmap 获取数据时,都会调用一个哈希函数。每个函数调用都使用堆栈。甚至哈希函数也不是简单的一种原始操作。哈希函数越智能,它实现的代码就越复杂。同时在幕后使用树需要花费时间和代码来粘贴数据和重新排列配置单元。请注意,当使用哈希表比简单数组更有效时,没有人回答这个问题。
I wonder no one tell about performance of Hashmap's. Don't forget the fact a hash-function called each time one put data on Hashmap and getting data from a hashmap behind the scene. Each function call uses stack. And even hash function is not simple one primitive operation. The smarter hash-function the more complex code it implements. The same time using trees behind the scene takes a time and a code for pasting data and rearranging hives. Take note no one answered the question when using a hashtable become more efficient over simple array.