我正在尝试通过hibernate将从DB获取的大约500万个对象加载到一个hashmap中。我为2种类别(A& B)执行此操作。我遍历了pojos。 Key是pojo中的一个字段,值是pojo本身。
1。对于A类类型,键是整数字段。我可以在不到20秒的时间内加载地图。
对于B类2.a)测试1,我的键是一个字符串字段。当我尝试将这些对象加载到新的hashmap时(通过重新启动java进程进行重新尝试,所以不用担心GC),将100K对象加载到地图中大约需要30秒。
2.b)测试2,当我尝试使用此类中的不同字段(整数类型)并加载地图时,它的工作方式与第一个类似,并且在不到20秒的时间内加载。
2.c)测试3,我想知道问题是否是数据类型。所以对于B类,我尝试了另一种使用#2.b中的整数字段创建字符串键的方法。 (key = int_field +“”)并将其加载到< 20秒
另一个测试,测试4,我为类B类做的是我创建密钥的方式。对于2.c,我创建了这样的键
map.put(pojo.getIntField()+“”,pojo);
结果如上所述2.c.
2.d)但是当我在pojo中创建另一个getter时返回 int_field +“”并在地图中使用它作为
map.put(pojo.getIntFieldInStringForm(),pojo);
对于100K物体,性能恶化到约30秒。
我知道问题出在密钥上,因为我已经通过将结果对象添加到列表中来验证数据库提取阶段,并且它在<两种类型均为20秒。
我无法理解其原因。如果有人能够对此有所了解,那将会非常有帮助。非常感激。感谢
编辑:
在这里添加代码片段(原谅格式/拼写错误,如果有的话):
测试#1
Map<String, ClassA> map = new HashMap<String, ClassA>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassA> iterator = session.createQuery( "from ClassA" ).setFetchSize( 1000 ).iterate();
while ( iterator.hasNext() ) {
ClassB objClassA = iterator.next();
map.put( objClassB.getIntField(), objClassA );
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
测试#2.a
Map<String, ClassB> map = new HashMap<String, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery( "from ClassB" ).setFetchSize( 1000 ).iterate();
while ( iterator.hasNext() ) {
ClassB objClassB = iterator.next();
map.put( objClassB.getStringField(), objClassB );
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
测试#2.b
Map<Integer, ClassB> map = new HashMap<Integer, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery( "from ClassB" ).setFetchSize( 1000 ).iterate();
while ( iterator.hasNext() ) {
ClassB objClassB = iterator.next();
map.put( objClassB.getIntField(), objClassB );
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
测试#2.c
Map<String, ClassB> map = new HashMap<String, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery( "from ClassB" ).setFetchSize( 1000 ).iterate();
while ( iterator.hasNext() ) {
ClassB objClassB = iterator.next();
map.put( objClassB.getIntField() + "", objClassB );
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
测试#2.d
Map<String, ClassB> map = new HashMap<String, ClassB>();
Session session = sessionFactory.openNewSession();
try {
Iterator<ClassB> iterator = session.createQuery( "from ClassB" ).setFetchSize( 1000 ).iterate();
while ( iterator.hasNext() ) {
ClassB objClassB = iterator.next();
map.put( objClassB.getIntFieldInStringForm() + "", objClassB );
}
}
catch (Exception e) {
e.printStackTrace();
}
finally {
session.close();
}
答案 0 :(得分:1)
要将项目放在HashMap中,需要计算密钥的hashCode。如果您的字符串是8 - 10个字符,则需要进行一些计算以将它们映射到32位哈希码。你的整数键有多大?如果它们小于100.000,则只有5个字符来计算hashCode,因此速度要快一些。
当两个键计算相同的哈希码时,您的性能也会受到影响,这可能会使用您的String键几次。
当您使用唯一整数作为键时,哈希冲突永远不会发生。也许如果您使用转换为整数的字符串,则字符串哈希算法也会减少冲突。