HashMap常见问题

一、HashMap的数据结构?如何遍历最快

首先hashMap有一个静态内部类Node,并实现了Map.Entry接口;

 static class Node<K,V> implements Map.Entry<K,V> {
        final int hash;
        final K key;
        V value;
        Node<K,V> next;

        Node(int hash, K key, V value, Node<K,V> next) {
            this.hash = hash;
            this.key = key;
            this.value = value;
            this.next = next;
        }

Map.Entry接口中有获取key和value的方法

2、HashMap的底层是一个静态数据

 transient Node<K,V>[] table;

3、Node的结构是一个链表(hash冲突时使用)

4、遍历速度问题

4.1使用keySet遍历

        首要要在静态数据中将Key全部取出-->放到set中,如果需要再使用set中的key获取value时,需要再进行使用key从map中取值,map.get(k)使用的是hash检索模式

        --相对来说不是很快

4.2使用 Set<Map.Entry<Integer, Integer>> entries = mapp.entrySet();
        直接找到数组中的entry数据,放到set中,然后直接从entry中获取数据,

        --速度比keySet块(不需要先获取key,然后再根据key来检索)

二、map中的哈希冲突是什么?如何解决

map存放数据使用的是put方法,

   public V put(K key, V value) {
        return putVal(hash(key), key, value, false, true);
    }

因为hashMap的底层是静态数组,在存放新值的时候首选要确定数组下边,通过上边代码可以看到首选是通过key的hash算法来确定下标,如果此时下标没有数据则直接放入,如果此时该下标内已经有数据了,则会将新数据以链表的形式接着往下放;当然如果链表的下标>=7(长度大于等于8)的时候,链表结构会变成红黑树;

hash冲突本质就是静态数组的索引下标冲突;不是hash值冲突(hash值可能是不冲突的)

索引下标计算方法如下:

p = tab[i = (n - 1) & hash]

三、HashMap、Hashtable、ConcurrentHashMap之间的区别

HashMap没有锁
Hashtable整表锁
ConcurrentHashMap分段锁

        HashMap的方法都是不加锁的;

        Hashtable的主要方法都使用了synchronized进行同步,他锁住了当前对象;简单说就是锁了整个hash表,在高并发的情况下效率非常低;

        ConcurrentHashMap:分段锁

                1.7及之前

                使用的是Segment分段锁,继承了ReentrantLock类

                使用的是HashEntry的静态内部类

                1.8及以后

                和hashMap就一致了使用的也是node内部类,

                区别点在于比如在put方法中和hashMap的区别在于如果发生Hash冲突时,会锁住冲突下标的节点(也就是节点上的链表);大幅度简化了1.7的结构

synchronized锁的是当前对象?

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值