HashMap

132 阅读1分钟

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线程安全