HashMap的初始值:
hashmap有多个构造方法,
- HashMap()
- HashMap(int initCapacity)
- HashMap(int initCapacity,float loadFactor)
第一个无参构造new出来的就是默认大小initCapacity为16个键值对,加载因子loadFactor为0.75的hashmap,即put到13时则将capacity翻倍。所以默认状态的map容量总是2的n次方;
第二个构造方法则可以设置默认大小
第三个还可以设置加载因子,注意是float类型。
HashMap排序问题
HashMap的排序是一个不怎么让人舒服的话题,因为HashMap存在的意义就是通过散列值排序,达到通过下标访问超快速的目的。
hashMap内部维护HashTable,但线程不同步,存储按照key计算的hash值进行排列。hashMap没有Comparator匿名内部类,因为会破坏按照hash值存储的顺序。只能通过Collections.sort(list,c)进行排列
Map<String,String> hashMap = new HashMap<String,String>();
hashMap.put("bb", "baby");
hashMap.put("aa", "angela");
hashMap.put("dd", "david");
hashMap.put("cc", "cendy");
List<Map.Entry<String, String>> list2 = new ArrayList<Map.Entry<String,String>>(hashMap.entrySet());
Collections.sort(list2, new Comparator<Map.Entry<String, String>>() {
@Override
public int compare(Entry<String, String> o1, Entry<String, String> o2) {
return o1.getKey().compareTo(o2.getKey());
}
});
for(Map.Entry<String, String> entry:list2){
System.out.println(entry.getKey()+":"+entry.getValue());
}
所以一般情况下使用其有序子类LinkedHashMap
HashMap存储原理
hashMap内部维护HashTable,相当于一个数组。
下面是put方法的源码
可以看出每次存入key与value,int hash = hash(key.hashCode());重新计算hash值
根据这个hash值得到此元素在数组中的位置(下标),并存入;
如果当前位置已经存在其他元素,则在当前位置以链表的形式存储这些值,新加入的在链头,之前加入的在链尾。
public V put(K key, V value) {
// HashMap允许存放null键和null值。
// 当key为null时,调用putForNullKey方法,将value放置在数组第一个位置。
if (key == null)
return putForNullKey(value);
// 根据key的keyCode重新计算hash值。
int hash = hash(key.hashCode());
// 搜索指定hash值在对应table中的索引。
int i = indexFor(hash, table.length);
// 如果 i 索引处的 Entry 不为 null,通过循环不断遍历 e 元素的下一个元素。
for (Entry<K,V> e = table[i]; e != null; e = e.next) {
Object k;
if (e.hash == hash && ((k = e.key) == key || key.equals(k))) {
V oldValue = e.value;
e.value = value;
e.recordAccess(this);
return oldValue;
}
}
// 如果i索引处的Entry为null,表明此处还没有Entry。
modCount++;
// 将key、value添加到i索引处。
addEntry(hash, key, value, i);
return null;
}