Java 如何评估哈希表实现?(使用HashMap作为参考)
问题:Java 如何评估哈希表实现?(使用HashMap作为参考),java,performance,memory-management,hashmap,hashtable,Java,Performance,Memory Management,Hashmap,Hashtable,问题: 我需要比较两个哈希表实现(基本上是HashMap和另一个),并得出合理的结论 我对100%的准确度不感兴趣,只是我的估计方向正确而已 我不仅对每个操作的差异感兴趣,而且主要对哈希表作为“整体”的差异感兴趣 我对速度没有严格的要求,因此如果另一个实现合理地较慢,我可以接受它,但我确实期望/要求内存使用更好(因为其中一个哈希表由基元表支持) 到目前为止我做了什么: 最初,我创建了自己的自定义“基准测试”,使用循环和许多调用来提示gc,以了解差异,但我在网上看到,使用标准工具更可靠/更合适
- 我需要比较两个哈希表实现(基本上是
和另一个),并得出合理的结论HashMap
- 我对100%的准确度不感兴趣,只是我的估计方向正确而已
- 我不仅对每个操作的差异感兴趣,而且主要对哈希表作为“整体”的差异感兴趣
- 我对速度没有严格的要求,因此如果另一个实现合理地较慢,我可以接受它,但我确实期望/要求内存使用更好(因为其中一个哈希表由基元表支持)
我的方法示例(MapInterface只是一个包装器,因此我可以在实现之间切换):
int[]键=新的int[10000000];
字符串[]值=新字符串[10000000];
对于(int i=0;i最大值){
最大值=时间;
}
运行+=时间;
map=null;
map=createNewHashMap();
hintsToGC();
}
返回新的长[]{min,max,run};
}
public void hintsToGC(){
对于(int i=0;i<20;++i){
系统输出打印(“.”);
gc();
试一试{
睡眠(100);
}捕获(中断异常e){
e、 printStackTrace();
}
}
}
私有HashMapInterface createNewHashMap(){
if(jdk){
返回新的jdkhashmapprapper();
}
否则{
返回新的AlternativeHashMapWrapper();
}
}
公共类JDKHashMapWrapper实现HashMapInterface{
HashMap;
jdkhashmapprapper(){
hashMap=新的hashMap();
}
公共字符串put(整型键、字符串值){
返回hashMap.put(键,值);
}
//等
}
(我想测试放置
,获取
,包含
和内存利用率)我可以通过使用我的方法确定我可以得到合理的测量值吗?
如果不是,最合适的工具是什么?如何使用 更新:
-我还使用SecureRandom使用随机数(也就是~10M随机数)进行测试。
-当哈希表调整大小时,我打印哈希表的逻辑大小/实际表的大小,以获得负载因子 更新:
对于我的特殊情况,如果我对整数也感兴趣,那么我的方法会有哪些陷阱 在@dimo414评论后更新: 至少哈希表作为一个“整体”是没有意义的 我指的是哈希表在运行时和内存消耗的各种负载下的行为 每个数据结构都是不同方法的折衷 我同意。我的折衷方案是对内存改进的可接受访问惩罚 您需要确定您对验证哪些功能感兴趣 1) put(键、值)
2) 获取(键、值)
3) 康纳斯基(钥匙)
4) 所有这些,当哈希表中有许多条目时,我只是做了一些类似的事情,最后使用了中的内置探查器。您可以获得有关CPU和内存使用情况的详细信息。我最初是在Eclipse中编写所有代码的,但是Netbeans有一个导入特性,用于引入Eclipse项目,并且它将所有代码都设置为无问题的,如果您的情况也是这样的话 关于计时,您还可以查看ApacheCommons中的类。这是一种更直观的跟踪目标操作时间的方法,例如:
StopWatch myMapTimer = new StopWatch();
HashMap<Integer, Integer> hashMap = new HashMap<>();
myMapTimer.start();
for (int i = 0; i < numElements; i++)
hashMap.put(i, i);
myMapTimer.stop();
System.out.println(myMapTimer.getTime()); // time will be in milliseconds
StopWatch myMapTimer=新秒表();
HashMap HashMap=新的HashMap();
myMapTimer.start();
对于(int i=0;i
使用哈希表的一些关键考虑因素是“bucket”分配的大小、冲突解决策略和数据的形状。本质上,哈希表接受应用程序提供的密钥,然后将其哈希为小于或等于分配的桶数的值。当两个键值散列到同一个bucket时,实现必须解决冲突并返回正确的值。例如,可以为每个bucket设置一个排序的链表,然后搜索该链表
如果您的数据碰巧有很多冲突,那么您的性能将受到影响,因为哈希表实现将花费太多时间来解决冲突。另一方面,如果您有大量的存储桶,则会以牺牲内存为代价来解决冲突问题。此外,如果条目数量超过一定数量,Java的内置HashMap实现将“重新设置”——我认为这是一个值得避免的昂贵操作
自从你
StopWatch myMapTimer = new StopWatch();
HashMap<Integer, Integer> hashMap = new HashMap<>();
myMapTimer.start();
for (int i = 0; i < numElements; i++)
hashMap.put(i, i);
myMapTimer.stop();
System.out.println(myMapTimer.getTime()); // time will be in milliseconds
-javaagent: [PATH_TO]/classmexer.jar
MemoryUtil.deepMemoryUsageOf(mapIamInterestedIn, VisibilityFilter.ALL)