【Java】HashMap

1.Map.Entry与HashMap.Node类,Node里面有一个next方法,我们可以认为一开始的时候HashMap的存储是按照链表存储的。

static class Node<K,V> implements Map.Entrhy<K,V>{}

在HashMap存储数据增加到一定数量的时候(阈值),那么就会由链表变为红黑树(性能更快)


2.阈值,超过这个值就会变为红黑树

static final int TREEIFY_THRESHOLD = 8 

 

3.HashMap里面对于数据的保存个数哥扩充是按照倍数进行的,但是这里面有一个参考百分比:

static final float DEFAULT_LOAD_FACTOR = 0.75f

.如果达到了16*0.75个数的时候会进行第一次容量扩充,而后16会变成32


5.HahsMap里面的方法都是异步处理的,属于非线程安全的,如果是读没有问题,如果是边读边写的话就会报出:java.util.CocurrentModificationException,表示的就是你存储的个数和你操作的个数不同。

比如运行下面这个代码,就会出错。

HashMap<int,int> map = new HashMap<int,int>();
for (int x =0;x<10;x++){
    new Thread(()->{
        for(int y =0;y<3;y++){
            map.put(Thread.currentThread().getName(),"y="+y);
            //但是如果边读边写
            System.out.println(map);
        }
    }).start();
}

 

6.HashMap中 Hash冲突时会影响HashMap性能,如何解决。

  在整个Hash存储过程中,必须要明确俩个问题,hashCode()和equal()方法。如果hashCode()相同,这个时候会查询equals(),不过一般在使用Map的时候都会考虑使用String来实现,所以在String实现的Key里面是不存在这种复杂的概念,也就是说这样的概念只存在于自定义类里面,所以当Hash冲突严重的时候,首先去考虑从euqals()方法是否正常,那么在进行数据定位的时候会更加的快速。

  但是如果从实际的数据结构的算法来讲,那么真的有哈希冲突的时候就需要使用一些特定的处理方法“

  1.开放定址法:为一个哈希冲突求一个地址序列

  2.链地址法:将所有哈希冲突的内容保存在一个链表里面(HashMap的实现原理)

  3.再哈希法:重新做一个hash计算

 

7.HashMap需要resize时扩容因子时如何得到的?

  -在进行数据添加的时候这个里面存在一个put()方法

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

  -在put()方法里面可以发现有一个putVal()方法,而且可以发现这个方法首先进行了hash计算(查找),而后在这个方法的实现定义里面有一个resize()方法。是否大于最大的容量,如果是,将其设置为整形最大,如果不是,则进行一个30的移位-11110。

  -他的容量扩充指的是一开始放30个,如果不够进行移位处理,相当于30*2。

 

 

 

posted on 2020-02-13 23:09  雪原那么远  阅读(89)  评论(0编辑  收藏  举报

导航