一、初识Map接口
Map集合和Collection集合的区别:
Map集合是有Key和Value的,Collection集合是只有Value。
Collection集合底层也是有Key和Value,只是隐藏起来。
Map集合的特点:
一个映射不能包含重复的键,每个键最多只能映射到一个值。
要是当Map集合利用put方法添加相同的键时,从前的键对应的值将会被覆盖
二、HashMap集合
1、特点:
- 双列集合,存入的是(Key,Value),主要针对键的操作;
- 底层的实现利用Hash算法
- 集合输出的时候是无序的
- add()方法:当加相同的键时,从前的键对应的值将会被覆盖,并返回被覆盖的值。
是因为:HashMap还是运用了hash算法,重写他的equals和hascode方法
2、常用API:
方法摘要 | |
---|---|
void | clear() 从此映射中移除所有映射关系(可选操作)。 |
boolean | containsKey(Object key) 如果此映射包含指定键的映射关系,则返回 true。 |
boolean | containsValue(Object value) 如果此映射将一个或多个键映射到指定值,则返回 true。 |
Set<Map.Entry<K,V>> | entrySet() 返回此映射中包含的映射关系的 Set 视图。 |
boolean | equals(Object o) 比较指定的对象与此映射是否相等。 |
V | get(Object key) 返回指定键所映射的值;如果此映射不包含该键的映射关系,则返回 null 。 |
int | hashCode() 返回此映射的哈希码值。 |
boolean | isEmpty() 如果此映射未包含键-值映射关系,则返回 true。 |
Set<K> | keySet() 返回此映射中包含的键的 Set 视图。 |
V | put(K key, V value) 将指定的值与此映射中的指定键关联(可选操作)。 |
void | putAll(Map<? extends K,? extends V> m) 从指定映射中将所有映射关系复制到此映射中(可选操作)。 |
V | remove(Object key) 如果存在一个键的映射关系,则将其从此映射中移除(可选操作)。 |
int | size() 返回此映射中的键-值映射关系数。 |
Collection<V> | values() 返回此映射中包含的值的 Collection 视图。 |
3、Map集合的遍历:
①:利用迭代器和增强for循环遍历
Map<String,Integer> map = new HashMap<>();
map.put("张三",12);
map.put("李四",13);
map.put("王五",14);
/*利用迭代器遍历*/
/* Set<String> keySet = map.keySet(); //获取所有键的集合
Iterator<String> it = keySet.iterator(); //获取迭代器
while (it.hasNext()){
String key = it.next(); //获取每一个键
Integer value = map.get(key); //根据键获取值
System.out.println(key+"="+value);
}*/
/*增强for循环遍历*/
for(String key : map.keySet()){
System.out.println(key + "="+ map.get(key));
}
② 对Map.Entry对象进行遍历
将键值对封装为Map.entry对象,再用对象的getKey和getValue方法遍历
for(Map.Entry<String,Integer> en : map.entrySet()){//获取键的集合
System.out.println(en.getKey()+"="+en.getValue());//
}
三、 TreeMap
特点:可以对集合实现排序,重写Compareable接口
比较键的:重写Compareable接口对象进行比较,比较是的键。 或者传入比较器
注:具体实现可以参考TreeSet集合。
四、补充 LinkedHashMap 、Hashtable
①:LinkedHashMap特点:底层是链表,可以实现顺序存储。
②:Hashtable:
面试题: * 共同点:底层都是哈希算法,都是双列集合 * 区别:1、HashMap是线程不安全的,效率高,JDK1.2 * Hashtable是线程安全的,效率度,JDK1.0的版本 * 2、HashMap可以存储null键和null值 * Hashtable不可以存储null键和null值、会影响程序的进一步执行
五、运用Map集合做的一些小demo
①:从键盘输入 统计字符串中每个字符出现的次数
/*
* 从键盘输入 统计字符串中每个字符出现的次数
* 1、创建Scanner对象,接受输入的字符串
* 2、将字符串转换为字符数组
* 3、创建双列集合,存储字符和字符出现的次数
* 4、遍历字符数组,获取每个字符并将字符存储在双列集合中
* 5、存储过程中进行判断,如果集合无该字符,存储该字符,并将值设置为1,如如果存在则在原来的值基础上加1
* 6、遍历集合
* */
public class TotalCharNumberTest01 {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
String line = sc.nextLine();
char []arr = line.toCharArray();
HashMap<Character,Integer> hm = new HashMap<>();
for(Character c : arr){
/* if(!hm.containsValue(c)){
hm.put(c,1);
}else {
hm.put(c,hm.get(c)+1);
}*/
hm.put(c, !hm.containsKey(c) ? 1 : hm.get(c)+1 );
}
for(Map.Entry<Character,Integer> en : hm.entrySet()){
System.out.println(en.getKey()+"="+en.getValue());
}
for(Character key : hm.keySet()){//获取键的集合
System.out.println(key+"="+hm.get(key));//获取值得集合
}
}
}
②:利用map集合模拟斗地主发牌,洗牌,看牌,抢地主的效果
/* * 需求:模拟斗地主游戏 * 分析: * 1、生成一副扑克牌 * 2、洗牌 * 3、发牌 * 4、看牌:留三张底牌 * 5、抢地主 具体细节: * 大小关系:黑桃大于红心,红心大于梅花,梅花大于方块 * * 思路:第一步:利用双列集合(HashMap)将牌的的大小从小到大原始排序,并标上序号:键存储的是索引,值存储的是牌 * 例如:0---黑桃3 1---红心3 2---梅花3 3---方块3 * 第二部:利用ArrayList存储牌的索引 洗牌:对索引洗牌,再根据索引获取值 * 第三部:创建三个TreeSet集合,将各个人手中的牌通过对索引排序从而对卡牌进行排序 * */
public class PokerDemo {
public static void main(String[] args) {
/*
1、创建一副牌
*/
String[] num = {"3","4","5","6","7","8","9","10","J","Q","K","A","2"};
String[] color = {"黑桃","红心","梅花","方块"};
//创建一个双列集合,存储索引和牌
HashMap<Integer,String> hm = new HashMap<>();
//创建一个ArrayList集合存取索引,对索引操作,从而对牌进行操作
// 例如:0---黑桃3 1---红心3 2---梅花3 3---方块3
ArrayList<Integer> list = new ArrayList<>();
int index = 0;
//创建一副牌、并将索引存入ArrayList集合
for(String s1 : num){
for(String s2 : color){
list.add(index);
hm.put(index,s2.concat(s1));
index++;
}
}
//再加入大王、小王
hm.put(index,"小王");
list.add(index);
index++;
hm.put(index,"大王");
list.add(index);
// System.out.print(list);
/*
* 2、洗牌
* */
Collections.shuffle(list);
/*
* 3、发牌
* 定义三个TreeSet集合,模拟玩家;在定义一个TreeSet集合,模拟剩下的底牌
* */
TreeSet<Integer> hss = new TreeSet<>();
TreeSet<Integer> wys = new TreeSet<>();
TreeSet<Integer> xsc = new TreeSet<>();
TreeSet<Integer> dipai = new TreeSet<>();
for(int i=0;i<list.size();i++){
if(i>=list.size()-3){
dipai.add(list.get(i));
}else if(i % 3 == 0){
hss.add(list.get(i));
}else if(i % 3 == 1){
wys.add(list.get(i));
}else {
xsc.add(list.get(i));
}
}
/*
* 4、看牌
* 因为定义了三个集合模拟三个人,我们可以定义一个看牌的方法,来进行每个人的看牌
* */
lookPoke(hm,hss,"黄ss");
lookPoke(hm,wys,"王ys");
lookPoke(hm,xsc,"熊sc");
lookPoke(hm,dipai,"底牌是");
}
//看牌的方法:参数有传入定义索引对应的牌号集合HashMap;每个人TreeSet集合;姓名String
public static void lookPoke(HashMap<Integer,String> hm,TreeSet<Integer> ts,String name){
System.out.print(name+"的牌是:");
for (Integer i:ts){
System.out.print(hm.get(i)+" ");
}
System.out.println();
}
}