Map
储存键值对,保证键值的唯一性是通过HashMap中hash表
map集合常用方法
获取方法
遍历
通过KeySet方法,获取Map集合中所有的键的集合
通过values方法,获取Map集合中所有的值的集合
- Map第一种遍历方法
- 通过KeySet()方法获取所有键的集合
- 遍历键的集合,获取所有的键,使用增强for循环实现
- 根据键去找值,通过get(Object key)方法实现
public void test1(){ //创建集合对象 Map<String,String> cities = new HashMap<String,String>(); //put(K key,V value)将指定的值与该映射中的指定键相关联 cities.put("吉林省", "长春市"); cities.put("黑龙江省", "哈尔滨市"); cities.put("辽宁省", "沈阳市"); //获取所有键的集合。用keySet()方法实现 Set<String> keySet = cities.keySet(); //遍历键的集合,获取到每一个键。用增强for实现 for (String key : keySet) { //根据键去找值。用get(Object key)方法实现 String value = cities.get(key); System.out.println("key="+key + ",value=" + value); } }
- Map第二种遍历方法
- 通过entrySet()方法获取所有键值对的集合
- 遍历键的集合,获取所有的键值对,使用增强for循环实现
- 根据键和值去找键值对,通过getKey()方法获取Key;通过getValue()方法获取value
public void test1(){ //创建集合对象 Map<String,String> cities = new HashMap<String,String>(); //put(K key,V value)将指定的值与该映射中的指定键相关联 cities.put("吉林省", "长春市"); cities.put("黑龙江省", "哈尔滨市"); cities.put("辽宁省", "沈阳市"); //获取所有键值对对象的集合 Set<Entry<String,String>> ens = cities.entrySet(); //遍历键值对对象的集合,得到每一个键值对对象 for(Entry<String,String> en : ens){ //根据键值对对象获取键和值 String key = en.getKey(); String value = en.getValue(); System.out.println("key="+key + ",value=" + value); } }
HashMap的底层实现
hashMap的底层实现是哈希表
-
哈希表底层采用数组+链表实现,即使用链表处理冲突。
-
同一hash值的链表都存储在一个链表里。
-
但是当位于一个桶(数组)中的元素较多,即hash值相等的元素较多时,通过key值依次查找的效率较低。
-
而JDK1.8中,哈希表存储采用数组+链表+红黑树实现,当链表长度超过阈值(8)时,将链表转换为红黑树,这样大大减少了查找时间。
-
简单的来说,哈希表是由数组+链表+红黑树(JDK1.8增加了红黑树部分)实现的,如下图所示。
HashMap的put(k,v)实现
- 将k,v封装到Node(节点)对象中
- 底层会调用k的hashCode()方法得出hash值
- 通过哈希算法,将hash值转换为数组的下标,
- 如果该下标的位置上没有任何元素,就把这个Node添加到这个位置上。
- 如果该下标的位置上有链表,此时,就会将k和链表上的每个节点的k进行比较(使用equals()方法)
- 如果equals()方法返回的是false,则把这个新的节点添加到链表的末尾
- 如果equals()方法返回的是true,那么这个节点的value就被覆盖
HashMap的get(k)实现
- 调用hashCode()方法得出哈希值,通过哈希算法将其转换为数组的下标
- 通过上面获取的下标,可以快速定位到该下标的位置
- 如果该下标的位置上什么都没有,就返回null
- 如果该下标的位置上有单向链表,那么就会拿get(k)方法里面的k,与单向链表上的每一个节点比较(通过equals()方法)
- 如果通过4的equals()方法,返回的值是false,则get()方法返回null
- 如果通过4的equals()方法,返回的值是true,该节点的value就是需要找的value值,get()方法返回这个value值