Java集合框架(四)—Map
一、Map
Map存储的是k-v键值对映射的数据
1、特点
key-value映射
2、具体API操作
- 增加:
put(k,v):添加元素
Map<String,Integer> map = new HashMap<>(); map.put("a",1); map.put("b",2); map.put("c",3); map.put("d",4); System.out.println(map);
- 查找:
isEmpty:判断是否为空
size:返回map的大小
containsKey(k):
containsValue(v)
get(k)
System.out.println(map.get("a")); System.out.println(map.containsKey("c")); System.out.println(map.containsValue(1)); System.out.println(map.isEmpty()); System.out.println(map.size());
- 删除:
clear:清空集合中的所有元素
remove:删除指定元素
map.remove("a"); System.out.println(map); map.clear();//清空 System.out.println(map);
3、HashMap
- 存储结构:数组+链表(jdk1.7) 数组+链表+红黑树(jdk1.8)
- key无序,唯一(Set也具有唯一,无序的特点)
HashMap源码注意事项:
- HashMap初始值为2的N次幂(Must be a power of two):
1、方便进行&操作,提高效率,&要比取模运算效率要高
hash& (initCapacity-1)
2、在扩容之后涉及到元素的迁移过程,迁移的时候只需要判断二进制的前一位是0或者是1即可,如果是0,表示新数组和旧数组的下标位置不变,如果是1,只需要将索引位置加上旧数组长度值即为新 数组的下标
- 加载因子(load factor):与扩容有关,初始容量是16,当16*0.75时进行扩容,并不是在达到初始容量16时扩容
- jdk1.7源码知识点: 数组+链表
1、默认初始容量
2、加载因子
3、put操作
-设置值,计算hash
- 扩容操作
-数据迁移的过程 transfer
- jdk1.8源码知识点: 数组+链表+红黑树
1、判断链表长度若是超过8则转为红黑树(TREEIFY_THRESHOLD=8),这个阈值根据泊松分布得出的,在源码中实际是长度达到7时就会转为红黑树
if ((e = p.next) == null) { p.next = newNode(hash, key, value, null); if (binCount >= TREEIFY_THRESHOLD - 1) // -1 for 1st treeifyBin(tab, hash); break; }
HashMap 与HashTable的区别:
- HashMap线程不安全,效率比较高;HashTable线程安全,效率低
- HashMap中的key和value都可以为空,HashTable不允许为空
4、LinkedHashMap
存储结构:链表
有序的HashMap,速度快
TreeMap
存储结构:红黑树
有序,速度没有HashMap快
问题:Set与Map有关系吗?
采用了相同的数据结构,只是用于map的key存储数据。
5、遍历map
Map<String,Integer> map = new HashMap<>(); map.put("a",1); map.put("b",2); map.put("c",3); map.put("d",4); System.out.println(map);
- 方法一
System.out.println("-------------遍历:根据key获取value----------------------"); //遍历 ,根据key获取值 Set<String> key = map.keySet(); for(String keys:key){ System.out.println(keys+"="+map.get(keys)); }
- 方法二
System.out.println("-------------遍历:获取value----------------------"); //只能获取对应的value值,不能根据value来获取key Collection<Integer> values = map.values(); for(Integer i:values){ System.out.println(i); }
- 方法三
System.out.println("-------------遍历:迭代器----------------------"); Set<String> key2 = map.keySet(); Iterator<String> iterator = key2.iterator(); while (iterator.hasNext()){ String keyIterator = iterator.next(); System.out.println(keyIterator+"="+map.get(keyIterator)); }
- 方法四
Map.entry:表示的是K-V组合的一组映射关系,key和value成组出现
System.out.println("-------------遍历:entrySet()---------------------"); Set<Map.Entry<String, Integer>> entries = map.entrySet(); Iterator<Map.Entry<String, Integer>> iterator1 = entries.iterator(); while (iterator1.hasNext()){ Map.Entry<String, Integer> next = iterator1.next(); System.out.println(next.getKey()+"--"+next.getValue()); }
二、Collections工具类
Collections和Collection不同,前者是集合的操作类,后者是集合接口
Collections提供的静态方法:
- addAll():批量添加
- sort():排序
- binarySearch():二分查找(注意:二分查找的时候需要先进行排序操作,如果没有进行排序,是找不到指定元素的)
- fill():替换(填充)
- shuffle():随机排序
- reverse():逆序
List<String> list = new ArrayList<>(); //list集合添加元素的两种方式 list.add("ad"); list.add("fgc"); Collections.addAll(list,"r","opwgh","poprewq"); //默认根据字母表进行排序 Collections.sort(list); //也可以自定义内部比较器,按字符串长度进行比较 Collections.sort(list,new Comparator<String>() { @Override public int compare(String o1, String o2) { if(o1.length()>o2.length()){ return 1; }else if(o1.length()<o2.length()){ return -1; }else{ return 0; } } }); //逆序 Collections.reverse(list);