我提出了一个非常大胆的想法。那就是我想使用HashMap
代替数据库来存储聊天应用程序的数据。
因此,当用户发送聊天消息时,该特定用户的聊天消息将使用HashMap
存储到storeMsg()
。
每个用户都有一个独立的聊天室。每隔5秒,该特定用户的聊天室将发送getMsg()
方法以检索该聊天室内的最新消息。检索邮件后,它会删除与该特定用户的聊天室相关的所有邮件,以便我们可以避免开销。
因此,只有用户存在于聊天室才能看到消息,消息可以一个一个地添加。最近进入该聊天室的新用户将无法看到之前的消息。这类似于点对点聊天。
每个用户都有一个唯一的字符串用户名,例如“tomhan12”,“Mary2”,“123cat”等。
public void storeMsg(String userName, String message){
hMap.put(userName, message);
}
public String getMsg(String userName){
return hMap.get(userName);
}
所以,我的问题是如果hMap
有Key
s String
s&如果hMap
有数百万条记录,那么hMap.get(str)
的速度会受到影响吗?
我们可以将String userName
转换为唯一的整数&然后“hMap.put(thatUniqueIntegerNumber, message)
”获得更高的性能?或者HashMap为我们做了这个,所以我们不需要这样做?
答案 0 :(得分:7)
HashMap
' get
具有预期的恒定运行时间,这意味着其运行时间不应取决于HashMap
的大小。当然,这取决于您的密钥的hashCode
方法的正确实现,但您的密钥是String
,因此它不应该是一个问题。
也就是说,使用大HashMap
(或任何其他大型数据结构)会占用大量内存,所以你应该注意你没有遇到内存不足的问题,这会减慢你的速度。应用
答案 1 :(得分:2)
如果key get()
函数具有良好的分布(对字符串来说是真的),则HashMap hashCode()
方法提供O(1)时间复杂度。地图的大小不会影响操作性能(从技术上讲,当地图变大时,碰撞更频繁发生,但这是另一个故事)。
使用String
键替换Integer
键不会给您带来任何显着的性能提升。
答案 2 :(得分:1)
https://docs.oracle.com/javase/7/docs/api/java/util/HashMap.html
此实现为基本操作(get和put)提供了恒定时间性能,假设散列函数在桶之间正确地分散元素。对集合视图的迭代需要与HashMap实例的“容量”(桶的数量)加上其大小(键 - 值映射的数量)成比例的时间。因此,如果迭代性能很重要,则不要将初始容量设置得太高(或负载因子太低)非常重要。
HashMap的一个实例有两个影响其性能的参数:初始容量和负载因子。容量是哈希表中的桶数,初始容量只是创建哈希表时的容量。加载因子是在自动增加容量之前允许哈希表获取的完整程度的度量。当哈希表中的条目数超过加载因子和当前容量的乘积时,哈希表将被重新哈希(即,重建内部数据结构),以便哈希表具有大约两倍的桶数。 / p>
作为一般规则,默认负载系数(.75)在时间和空间成本之间提供了良好的权衡。较高的值会减少空间开销,但会增加查找成本(反映在HashMap类的大多数操作中,包括get和put)。在设置其初始容量时,应考虑映射中的预期条目数及其加载因子,以便最小化重新散列操作的数量。如果初始容量大于最大条目数除以负载因子,则不会发生任何重新连接操作。
由于HashMap将其值存储在散列桶中,因此通常可以在O(1)和O(N)之间进行查找,具体取决于映射散列的散列冲突量。
为了测试Map的性能,我们将运行一个测试,首先将100/100000个项目插入到地图中,然后我们在循环中调用get(“0-9”)来测试性能查找。我们使用以下代码执行此操作:
import java.util.HashMap;
public class HashMapTest {
public static void test(int items, boolean print) {
System.gc();
System.gc();
HashMap<String,Object> map = new HashMap<>();
for(int i = 0; i < items; i++) {
map.put("" + i, map);
}
long start = System.nanoTime();
for(int i = 0; i < 100000; i++) {
map.get("0");
map.get("1");
map.get("2");
map.get("3");
map.get("4");
map.get("5");
map.get("6");
map.get("7");
map.get("8");
map.get("9");
}
long end = System.nanoTime();
long time = end - start;
if(print) {
System.out.println("items: "+ items + " time: "+ time);
}
}
public static void main(String ... args) {
// warmup
for(int i = 0; i < 2; i++) {
test(100, false);
}
for(int i = 0; i < 2; i++) {
test(1000000, false);
}
// Real test:
for(int i = 0; i < 10; i++) {
test(100, true);
}
for(int i = 0; i < 10; i++) {
test(1000000, true);
}
}
}
items: 100 time: 11102830
items: 100 time: 12228567
items: 100 time: 34309933
items: 100 time: 36976824
items: 100 time: 34290557
items: 100 time: 19819022
items: 100 time: 14747533
items: 100 time: 15818922
items: 100 time: 15026368
items: 100 time: 16830762
items: 1000000 time: 12421862
items: 1000000 time: 13931351
items: 1000000 time: 13083504
items: 1000000 time: 11453028
items: 1000000 time: 13265455
items: 1000000 time: 11030050
items: 1000000 time: 11362288
items: 1000000 time: 11521082
items: 1000000 time: 11198296
items: 1000000 time: 11303685
items 100 min: 11102830
items 100 max: 36976824
items 1000000 min: 11030050
items 1000000 max: 13931351
如果我们分析测试结果,我们发现访问时间没有“真正的”改善,我们有1000多个项目。
答案 3 :(得分:0)
理论上HashMap#get(...)
保证O(1),如果地图不是人口过多而且项目在桶之间正确分配。实际这是依赖于实现的,但如果人口过多,通常Map会慢一点。通常,HashMap
的负载系数应低于0.7,以避免人口过剩并保持最佳性能。虽然减速很小(除了一些极端情况)。