接口Map<k,v>的方法介绍及其底层的实现

一、方法

Map是一个键值对结构的数据类型
  key:我们要通过key去找我们对应的值
  value:我们存放的具体信息
  我们存储的信息都是以key作为标识,所以key不能重复
          如果key信息重复,后面会把前面的给覆盖掉

增:put ( K key , V value ) :添加一个元素进入Map类对象末尾;因为元素的关键字是唯一的,当使用put方法的时候,该方法会将所添加元素,按照他所对应的关键字,添加到对应关键字位置,并覆盖原有权值,这时候,put方法就会把原有的对应该关键字的权值返回回来。

       putAll ( Maps < ? extends K , ?extends V > m) :将另一个Map类型对象添加至调用他的对象的末尾;

删:clear ( ) :清空调用该函数的Map类对象;

       remove ( Object k ) :移除关键字为k的元素;

改:put即可实现;

查:get ( Object k ) :获取对应关键字为k值的元素;这里需要注意一点的是,我们可以通过个get方法来判断对应的Map类对象是否存在,当然,这种判断方法用在对应的Hashtable类当中是最合适的,因为该类不会出现赋值为空的情况。但是,这并不表示着这种判断存在的方法只能用在Hashtable类中,在大多数情况下,我们都是将这种方法放在HashMap类中使用的,因为,实际上赋值为空的情况是没有意义的一般很少出现

       size ( ) :获取调用该函数的Map类对象的大小;

       value ( ) :返回调用他的Map类对象关于其中元素权值的一个Collection类对象,这个函数的作用就是为了拿值;

       set <k>  keySet ( ) :返回调用该方法的Map类对象的关键字的Set类视图;

       set <Map.Entry < k , v >>entrySet ( ) :返回调用该方法的Map类对象的元素映射关系的Set类视图,而这个关系的数据类型就是Map.Entry< k, v>;

判断:containValue ( Object v ) :判断调用该函数的类中是否有权值为v的元素;

       containKey ( Object k ) :判断调用该函数的类中是否有关键字为k的元素;

       isEmpty ( ) :继承自Object的通用方法。

 这里面我们需要强调的是两个方法,一个是entrySet,另一个是keySet。

  1.  //首先是keySet使用思想举例:  
  2.               sop("keySetcondition:");  
  3.               Set<String> set =map.keySet();  
  4.               Iterator<String> ite =set.iterator();  
  5.               for(String key; ite.hasNext(); key= ite.next())  
  6.               {  
  7.                      sop("key:"+key+"  "+"value:"+map.get(key));  
  8.               }  
  9.    
  10.               //然后我们来看一下entryKey的使用思想  
  11.               sop("entrySetcondition:");  
  12.               Set<Map.Entry<String,String>>set = map.entrySet();  
  13.               Iterator<Map.Entry<String,String>>ite = set.iterator();  
  14.               for(Map.Entry<String,String>en;ite.hasNext();en=ite.next())  
  15.               {  
  16.                      String key = en.getKey();  
  17.                      String value =en.getValue();  
  18.                      sop("key:"+key+"  "+"value:"+value);  
  19.               }  
  20.    
  21.        }  
  22.        public static void sop(Object obj)  
  23.        {  
  24.               System.out.println (obj);  
  25.        }  

二、底层实现

/**
 * Map
 * 创建对象
 * //默认的初始容量16
 * static final int DEFAULT_INITIAL_CAPACITY = 1 << 4;  
 * //默认的使用的大小是总大小的75%
 * static final float DEFAULT_LOAD_FACTOR = 0.75f;
 * //map中数组可用的大小
 * int threshold;
 * //map中数组存放数据大小
 * int size;
 * //创建对象的时候默认创建一个空的entry数组
 * transient Entry[] table = (Entry[]) EMPTY_TABLE;
 * 存放数据
 * 第一次存放数据
 * 首先检查数组是不是默认的,如果是第一次需要创建一个新的
 * 新创建的数组是entry类型的,大小为16,可用为12
 * 计算key的hash值,相对是唯一的
 * 然后根据数组的大小计算当前key所应该处于的索引位置
 * 然后创建新的entry将数据存放至数组
 * 第一次之后加入数据
 * 首先计算key对应的hash值,算出对应的位置索引
 * 判断当前key有没有指定值,
 * 如果已经存在值
 * 就会把原来的值返回,并且新的value覆盖掉原来的值
 * 如果已经不存在值
 * 我们还需要判断当前数组容量是否足够
 * 扩容大小为原来的两倍,可用的大小也为原来的两倍,总大小的0.75
 * 最后将其存放至容器
 * 取出数据
 * 首先判断map是否为空,为空直接null
 * 不为空,计算当前key的hash值,然后计算索引值
 * 取出map的数组中指定位置的entry,然后进行比较
 * 比较当前对象,如果当前对象不equals,开始比较单向链表中的entry
 * 比较的时候先比较hash && 如果hash都不一样,对象肯定不一样,提高效率
 *
 * 为什么map数组的大小只允许使用75%
 * 假如数组用满,他并不是将数组的每个索引全部占用
 * 当我们用对象的hash值去&数组大小的时候,不避免会产生相同的索引
 * 这样就会导致一个索引有可能存放两个不同key,这个时候使用单向链表解决
 * 首先数组索引指向新创建的entry,新entry有一个next属性会指向原来的entry对象,形成一个单向链表
 * 其实如果使用单向链表存储数据的时候,已经违背了map设计的思想
 * 所以我们最好重写每一个对象的hashcode方法
 * 当我们的map里面的数组进行扩容的时候,当扩容完毕,首先散列我们现有存储的对象,尽量吧存在链表的地方给分开,提高查询效率
 *
 * Entry:记录
 * 我们map为了存放数据,所以专门创建的一个静态内部类
 * 类似于我们数组中的一个元素
 * entry里面有两个属性
 * key
 * value
 * 另外为了避免一些问题:不同hash算出相同index
 * next:
 * 另外为了查找更加的快捷,专门记录了key的hash值
 * hash:比较的时候线比较hash值
 *
 * hashmap中可以存放空值



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值