双例集合Map,HashMap常用方法及源码分析
Map:采用key_value存储数据,
Map接口:存储的是一对一对的数据,采用key-value存放
|---->HashMap:主要实现类,线程不安全,效率高;允许添加null的key或null的value
|------>LinkedHashMap:HashMap的子类,可以实现按照添加1的顺序实现遍历
对于频繁的遍历操作,建议使用此接口实现类
|---->TreeMap:可以按照元素的指定属性的大小实现遍历
|---->HashTable:古老实现类.线程安全,效率低,不允许添加null的key或null的value
|---->properties:常用来处理属性文件,key和value都是String类型
Map的结构:<1.Map中的key是无序的,不可重复的,key构成的集合是Set
<2.Map中的value是无序的,可以重复的,value构成的集合是Collection
<3.Map中的键值构成一个entry
<4.Map中的entry是一个set集合,无序,不可重读的
Map的常用方法:
增:put(Object key, Object value)将指定的key-value添加到map对象 ,putAll(Map m)将m中的所有键值对返回map中去
删:remove(Object,key)指定移除对应key的key-value对,并返回value
改:put(Object key,Object value)将指定的key-value修改到map对象
查:get(Object key):获取指定key的value containsValue(Object value)是否包含指定的value
长度:size()
遍历:KeySet()返回所有key构成的set集合 values()返回所有Value值构成的Collection集合 enterySet()返回所有的key- vlaue构成的set集合
HashMap:
HashMap的底层实现
jdk7:数组+单向链表,底层生成Entry[ ]数组
HashMap map =new HashMap();//Entry[] table=new Entry[16];
........
map.put(key1,vlaue1);//key1-value1会封装到一个entry对象中,将此对象放于table数组中,
首先根据key1所在的类的hashCode方法,计算key1的哈希值1,然后通过某种算法,生成得到哈希值2,
再使用IndexOf()方法获得它在底层table数组的存放位置
总结:先成底层空间为16的数组,在存放第一个数据时,生成特有的哈希值1,经由算法生成哈希值2,
去操作indexOf()方法得到他的存放位置
- 如果index位置是哪个没有元素,则key1-value1,添加成功
- 如果index位置上有(key2-value2),则比较key1和key2的哈希值
- ----->两者哈希值不同,则添加成功,此时数据存放在数组的位置上
- ----->两者哈希值相同,比较可以所在类的equals方法,将key2作为参数传递到此方法中,比较两个key是否相同,若相同则将value2替换value1,在插入到当前的index位置 ,此时存放的数据放于链表中,位于链表首部
这就是Map集合特有的key必须不同,value可以相同
扩容:--------->当添加的数据达到临界值时(=数组的长度1*加载因子),时进行扩容,默认扩容为2倍
jdk8:数组+单向链表+红黑树
- 当使用空参构造器,创建对象时,底层没有创建长度为16的数组
- 当我们首次使用put()添加数据时,底层会创建长度为16的数组
- 底层创建的数组是Node[ ]
- 当某个索引位置的链表长度>8,且数组长度>64时,将此索引位置上的元素,使用红黑树存储
- 形成链表时,新添加到元素放在链表结尾
HashMap的常用方法:
@Test public void test() { Map map =new HashMap<>(); Map map1=new TreeMap<>(); //增,put() map.put("aa", 98); map.put("bb", 948); map.put("vv", 938); map.put("dd", 928); map.put("gg", 918); System.out.println(map); //改put() map.put("aa", 111); System.out.println(map); //删remove() map.remove("gg"); System.out.println(map); //查get() System.out.println(map.get("aa")); } @Test public void test1() { Map map =new HashMap<>(); //增,put() map.put("aa", 98); map.put("bb", 948); map.put("vv", 938); map.put("dd", 928); map.put("gg", 918); //返回所有的key构成的Set集合 Set keySET=map.keySet(); System.out.println(keySET); //遍历key构成的Set集合 Iterator it=keySET.iterator(); for (Object object : keySET) { System.out.println(object); } //返回所有value构成的Collection集合 Collection c=map.values(); //遍历values构成的Collection集合 Iterator it1=c.iterator(); while (it1.hasNext()) { System.out.println(it1.next()); } //返回键值对构成的Set集合 Set s=map.entrySet(); Iterator it2=s.iterator(); for (int i = 0; i < s.size(); i++) { System.out.println(it2.next()); } }
TreeMap:指定排序方式,添加的数据必须是同一个类创建的对象,必须重写Equals()方法和hashCode()方法