hashMap的底层实现

hashmap的底层实现

hashmap是根据键的hashcode值来存储数据的,大多数情况下可以直接定位到它的值,所以它的访问速度很快,但是遍历顺序不确定。

这是因为hashmap会先用hash函数处理键值,让其能够均匀分布到map中

hashmap最多只允许一条记录的键为null,单允许多条记录的值为null。

hashmap是非线程安全的,即任一时刻可以有多个线程来写hashmap,这可能会导致数据不一致。如果需要满足线程安全,可以用Collections的SynchronizedMap方法使hashMap具有线程安全的能力,或者使用ConcurrentHashMap。

ConcurrentHashMap在写入和读取的性能都比使用SynchronizedMap更高效

hashmap的结构是数组加链表,在JAVA8中又引入了红黑树

大体来说:HashMap里面是一个数组,然后数组中每个元素是一个单向链表。链表中存储的对象是嵌套类Entry的实例

Entry包含四个属性:key,value,hash值和用于单向链表的next。

根据hash值我们能快速找到数组的具体下标,但那是在这之后,需要顺着链表一个个比对才能找到所需要的值,,时间复杂度取决于链表的长度,为O(N)。为了降低开销,在Java8中设置当链表元素超过8个以后,会将链表转化为红黑树,在这些位置查找的时候可以降低时间复杂度为O(logN)。

capacity:当前数组容量,始终保持2^n,可以扩容,扩容后数组大小为当前的2倍

loadFactor:负载因子,默认为0.75

threshould:扩容的阈值,等于capacity*loadFactor

hashmap初始化时,可以指定初始化容量和阈值,如果指定,则初始化时阈值等于容量(不指定则为0)

当放入元素后,阈值就等于容量*负载因子

当元素数量超出阈值,hashmap会扩容为原来的2倍

public class TestField {
    /**输出hashmap的容量,阈值和元素数量*/
    private static void getMyMap(HashMap<?,?> map) throws Exception {
        Class<? extends HashMap> mapClass = map.getClass();
        //数组容量
        Method capacity = mapClass.getDeclaredMethod("capacity");
        capacity.setAccessible(true);
        //负载因子
        Method loadFactor = mapClass.getDeclaredMethod("loadFactor");
        loadFactor.setAccessible(true);
        //扩容阈值
        Field threshold = mapClass.getDeclaredField("threshold");
        threshold.setAccessible(true);
        System.out.println("容量:" + capacity.invoke(map) +
                ",负载因子:" + loadFactor.invoke(map) +
                ",阈值:" + threshold.get(map) + ",元素数量:" + map.size());
    }
    public static void main(String[] args) throws Exception{
        //不指定容量,初始阈值为0
        //HashMap<Integer,String> map = new HashMap<>();
        //指定初始化容量,阈值等同于容量
        HashMap<Integer,String> map = new HashMap<>(15);
        //指定容量和负载因子
        //HashMap<Integer,String> map = new HashMap<>(10,0.5f);
        getMyMap(map);//容量:16,负载因子:0.75,阈值:16,元素数量:0
        map.put(1,"test");
        getMyMap(map);//容量:16,负载因子:0.75,阈值:12,元素数量:1
        for (int i = 2; i <= 12; i++) {
            map.put(i,"t");
        }
        getMyMap(map);//容量:16,负载因子:0.75,阈值:12,元素数量:12
        map.put(13,"t");
        getMyMap(map);//容量:32,负载因子:0.75,阈值:24,元素数量:13
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值