1、以下两种方式有何区别吗?
Map<String,Object> map = new HashMap<>();
a:for (String key : map.keySet()){
Object bean = map.get(key);
}
b:for (Map.Entry<String,Object> entry:map.entrySet()){
Object bean = entry.getValue();
}
c:map.forEach((key,value) -> {
});
要回答这个问题,需要看下涉及到的源码:
public Set<K> keySet() {
Set<K> ks = keySet;
if (ks == null) {
ks = new KeySet();
keySet = ks;
}
return ks;
}
public V get(Object key) {
Node<K,V> e;
return (e = getNode(hash(key), key)) == null ? null : e.value;
}
public Set<Map.Entry<K,V>> entrySet() {
Set<Map.Entry<K,V>> es;
return (es = entrySet) == null ? (entrySet = new EntrySet()) : es;
}
@Override
public void forEach(BiConsumer<? super K, ? super V> action) {
Node<K,V>[] tab;
if (action == null)
throw new NullPointerException();
if (size > 0 && (tab = table) != null) {
int mc = modCount;
for (int i = 0; i < tab.length; ++i) {
for (Node<K,V> e = tab[i]; e != null; e = e.next)
action.accept(e.key, e.value);
}
if (modCount != mc)
throw new ConcurrentModificationException();
}
}
通过源码展示,最低效的就是a,需要每次去get;
此时有两个疑问?
第一种方法中的keySet在什么时候填充的?
第二种方法中的entrySet在什么时候填充的?
2、看下Map的put方法:
注意下出现hash冲突时,使用单链表(Node)还是红黑树(TreeNode)
初始化或扩容:resize()
计算新的容量、上限值,将旧的数组复制到新的数组中
3、与ConcurrentHashMap有啥区别:
1、HashMap可以map.put(null,null),ConcurrentHashMap不可以会抛异常
2、对于key的hash算法不一样
3、ConcurrentHashMap线程安全