------Java培训、Android培训、iOS培训、.Net培训、期待与您交流! -------
今天开始学Map集合
一.Map集合
双列集合,K-Key,V-Value,键都是不能重复的,每个键映射一个值.
Map和Collection的区别
1.双列,单列
2.Map的键唯一,Collection的子体系Set唯一
3.Map的数据结构针对键有效,跟值无关,Collection的数据结构针对元素有效.
问:到底是Map底层依赖Set还是Set底层依赖Map呢?
源代码中发现Map的put方法中没有Set支持,而Set的add方法中是由Map的put方法支持的,也就是说Set依赖Map.所以Set是put时,每个值都用一个private static final Object PRESENT=new Object();这样一个常量对象来隐藏.
为什么要用双列支持单列呢?
画图解释:双列支持单列的时候,只要用一套哈希算法就可以了,隐藏一列比较容易,如果是用两个单列来构造双列,那就比较麻烦
二.Map集合的功能概述
1.添加
put的时候,如果这个键的位置是null,那么添加时,就会返回null,如果这个键的位置已经有了一个值,那么就会覆盖这个值,并且返回原来那个值.
2.删除
remove时,会返回删除的这个键对应的值.
3.判断
boolean containsKey()
boolean containsValue()
boolean isEmpty()
4.获取
get()通过键获取值
values()获取所有值Collection
keyset()获取所有键Set
entrySet()所有键值对EntrySet
三.Map遍历键找值
Map没有迭代器,所以不能直接迭代,那么双列集合如何迭代呢?
先用keySet获取所有键,再通过遍历这个Set和get方法来获取所有值.
四.Map集合的键值对
通过entrySet方法获取所有键值对,再通过遍历这个Set和getKey,getValue方法来获取所有值和所有键.
Map.Entry到底是什么呢?
Entry就是Map中的一个内部接口,想要实现Entry,必须先找到Map,所以是Map.Entry.
五.键值对对象和源码分析
如果用Map.Entry的话就是父类引用指向子类对象,如果直接用Entry就是直接获取子类对象.源码中写了一个Entry实现了Map.Entry接口.
发现自定义对象没有覆盖,因为没有重写hashCode和equals方法,跟Set是一个道理.
为什么直接输出HashMap是键=值的格式?
因为Map中肯定重写了toString方法.
源码中在AbstractMap中找到toString方法.
六.LinkedHashMap
底层是链表实现的,所以是有序的.
七.TreeMap
和TreeSet一样,也要给定排序方法.
1.排序的类来实现Comparable,重写compareTo
2.新建类来来实现Comparator,重写compare
八.统计字符串中每个字符出现的次数
九.集合嵌套
HashMap嵌套HashMap
其实就是把HashMap放在另一个HashMap的键或值上,甚至键和值.
十.HashMap和Hashtable的区别
Vector被ArrayList替代了
Hashtable被HashMap替代了
共同点:
1.底层都是哈希算法.
2.都是双列集合
区别:
1.HashMap是线程不安全的,因为不同步,效率高.JDK1.2版本
Hashtable是线程安全的,因为同步,效率低,JDK1.0版本
2.HashMap可以存储null键和null值
Hashtable不可以存储
十一.Collections工具类
为集合的操作提供很多方法.方法全都是静态的.私有了构造方法.为了不能创建该类对象,就用类名直接调用方法.
1.sort()方法
Collections.sort(***),传入即可排序.
2.binarySearch二分查找法
Collections.binarySearch(***,key)
3.max找最大的,传入集合
4.revers反转,传入集合
5.shuffle,随机排序,传入集合
十二.模拟斗地主洗牌发牌.
分析:
1.买一副扑克,其实就是自己创建一个集合对象,将扑克牌存储进去.
2.洗牌,调用shuffle方法
3.发牌
4.看牌
String[] num={1,2,3};
String[] color={"红桃","黑桃"};
ArrayList poker=new ArrayList();
for(String s1:color){
for(String s2:num){
poker.add(s1+s2);
}
}
poker.add("小王");
poker.add("大王");
//洗牌
Collections.shuffle(poker);
//发牌
ArrayList a1=new ArrayList();
ArrayList a2=new ArrayList();
ArrayList a3=new ArrayList();
ArrayList 底牌=new Arraylist();
for(int i=0;i<poker.size();i++){
if(i>=poker.size()-3){
底牌.add(poker.get(i));
}else if(i%3==0){
a1.add(poker.get(i));
}else if(i%3==1){
a2.add(poker.get(i));
}else {
a3.add(poker.get(i));
}
}
//看牌
sysout(a1);
sysout(a2);
sysout(a3);
sysout(底牌);
十五.集合框架(泛型固定下边界)
1.泛型固定下边界
? super E
构造了一个Student类型的比较器,子类BaseStudent也可以用,为什么呢,因为这里有一个泛型Student.
2.泛型固定上边界
? extends E
addAll方法--把一个集合中的所有元素都添加到元素中.
两个ArrayList,List2的元素是List1的子类,添加元素,list1.addAll(list2),也就是说固定了上边界.其实很简单,list2中的元素的类型如果大于或者不等于list1中的元素,当然就添加不进去.