深入map和set
来源:互联网 发布:蜀美网络招聘信息 编辑:程序博客网 时间:2024/05/18 01:22
对HashSet而言 系统采用hash算法决定集合的快速存取,集合元素,对HashMap而言,系统采用hash算法,跟据hash值来获取的key的存取位置,实现快速存取;
HashMap类的put源码:
public V put(K key,V value){
if(key==null)
return putForNullKey(value);
//根据key的keyCode计算hash
int hash=hash(key.hashCode());
//搜索指定的hash值在对应table中的索引
int i=indexFor(hash,table.length);
//获取table中的entry对象
for(Entry<K,V> e=table[i];e!=null;e=e.next){
Object k;
//判断key的hash值是否相等同时key equal是否相同
if(e.hash==hash && ((k=e.key)==key||key.equals(k)){
V oldValue=e.value;
e.value=value;
e.recordAccess(this);
return oldValue; //把老的值替换成新的值
}
}
//如果i处索引为空
modCount++;
//创建新的entry对象
addEntry(hash,key,value,i);
return null;
}
向hashMap添加key-value的时候,由其key的hashcode返回值,决定该key-value (entry对象)的存储位置;
当两个entry对象的key的hashCode返回值相同时候,将有key的euqals的比较值来比较是否为true,如果为true则覆盖,否则会产生新的entry对象;
//添加新entry对象
void addEntry(int hash,K key, V value,int buckIndex){
Entry<K,V> e=table[buckIndex];
table[buckIndex] =new Entry<K,V>(hash,key,value,buckIndex);
if(size++>=threshold) //如果ket-value对的数量超出了极限
resize(2*table.length); //进行扩容操作
}
这个代码设计很吊,如果table[buckIndex]处有entry对象,则新创建的对象则指向本来就有的对象,所以就形成了一个entry链,所以新创建总是entry在链的末尾;//指定初始化容量,负载因子创建hashMap
public HashMap(int intialCapacity,float loadFactory){
if(intialCapacity<0)
throw new 异常;
if(intialCapacity>MAXMUM_CAPACTITY)
intialCapacity=MAXMUM_CAPACTITY;
if(loadFactory<0||Float.isNaN(loadFactory))
throw new 异常;
int capacity=1;
while(capacity<intialCapacity) //capacity小于初始化的值,则capacity扩大为2 的n次方
capacity<<1;
threshold=(int)(intialCapacity*loadFactory); //最大极限值则是初始化值*负载因子
table=new Entry[capacity]; //创建一个新的Entry对象数组
int(); //进行初始化操作;
}
初始化的时候,会产生一个table数组,这个数组里面放的元素,我们称作为“桶” bucket,每个bucket会有相对应的索引,我们可以根据索引来进行取值;
public V get(Object key){
if(key==null)
return getForNullKey();
int hash=hash(key.hashCode);
for(Entry[K,V] e=table[indexFor(hash,table.length)];e!=null;e=e.next)
{
Object k;
if(e.hash==hash&&((k==e.key)==key.equals(k))
return e.value;
}
return null;
}
如果hashmap只有一个entry对象,则hashmap通过索引直接取出该桶内的entry,如果是一条entry链,则就会遍历全部,如果该要找到的对象在该链的底部的最后一个entry,
所以要重写equals和hashCode来进行判断是否相同。如果一条entry链全部遍历则会降低hashMap的性能;
hashMap的默认是16
总的来说:
HashMap底层是key-value对当成整体进行处理,这个整体就是entry对象;底层则是一个Entry[]来保存所有的key-vaue对,当需要存储一个entry对象,会根据hash算法,来存到相应的位置,如果要取一个entry对象,也会根据hash算法来找到相应的位置进行获取;
hashMap一开始的时候初始化,不要空间大小不要初始化的太高;
负载因子默认是0.75,增大负载因子,会提高hashMap内部查询例如put,get。;降低负载因子,会提高hashMap的查询,反而增大了hashMap的空间开销
总的来说set底层就是hashMap,为了要符合hashMap的key-value对所以hashSet底层定义了一个静态的object类可以充当value;
set集合只是用了map的key而没有用value;
- 深入map和set
- 带你深入理解STL之Set和Map
- 带你深入理解STL之Set和Map
- 关于map 和set
- Map 和 Set 容器
- map和set异同
- set和map
- List Set和Map
- map 和 set
- List、Set和Map
- map和set异同
- set和map总结
- Javascript Map和Set
- js Map和Set
- 论set和map
- js Map和Set
- set和map
- List、Set和Map
- 程序猿的生活
- 绝对居中
- fcgi库两种编程风格
- Android控件ListView获取item中EditText值
- 匈牙利算法
- 深入map和set
- 快速原型工具 mockups和墨刀还有axure
- Apache kylin开发环境搭建
- 自定义注解之编译时注解(RetentionPolicy.CLASS)(三)—— 常用接口介绍
- Linux From Scratch(介绍)
- 自定义View(类似验证码)
- 为什么不能同时满足CAP原则
- 每周2要有一个提醒,程序内怎么实现
- oracle创建用户和表空间