一、Map集合
1、Map集合中常见的方法。
Map是一个接口,是所有双列集合的根接口
Map<K,V>有两个泛型, K 表示的是键的数据类型, V表示的是值的数据类型。
常见方法:
(重要)V put(K key, V value): 向Map集合中添加键值对
(重要)V get(Object key):根据键获取对应的值。
V remove(Object key): 根据键删除整个的键值对。
注意: put方法调用的使用如果key已经存在,那么就会覆盖掉原来的键值对。
public class Demo01MapMethod {
public static void main(String[] args) {
//创建一个Map集合,key是Integer,value是String
Map<Integer, String> map = new HashMap<>();
//调用put方法,向Map集合中添加键值对元素
map.put(100, "刘德华");
map.put(200, "张学友");
map.put(300, "黎明");
//打印Map集合
System.out.println(map);
//V get(Object key):根据键获取对应的值。
System.out.println(map.get(100)); //获取100对应的值并直接打印
System.out.println(map.get(10000)); //如果key不存在,那么结果是null。
//V remove(Object key): 根据键删除整个的键值对。 返回的是被删除键值对的值.
String str = map.remove(300); //将key为300的键值对删除。
System.out.println(map); // {100=刘德华, 200=张学友}
System.out.println("str:" + str);
System.out.println("=============================================");
//创建一个Map集合,key是String,value也是String
Map<String, String> map2 = new HashMap<>();
//添加元素
map2.put("it001", "大幂幂");
map2.put("it002", "柳岩");
map2.put("it003", "郭德纲");
//map2.put("it003", "于谦");//如果使用put方法向Map中添加的键值对中的key已经存在,那么就会把之前的键值对覆盖掉。
System.out.println("map2:" + map2);
//调用put方法时,如果没有产生覆盖效果,那么返回的是null
//如果产生了覆盖效果,那么返回值为被覆盖掉的值。
System.out.println(map2.put("it004", "赵本山")); //null
System.out.println(map2.put("it004", "宋丹丹")); //赵本山
}
}
2、遍历Set集合,还有一种方式,是EntrySet遍历。
遍历步骤:
1. 调用Map集合的entrySet方法获取到Map集合中的所有的Entry对象。
2. 遍历存放Entry对象的Set集合,拿到里面的每一个Entry对象。
3. Entry对象中保存了键值对,我们可以调用方法获取到键和值。
Map集合中获取所有Entry对象的方法:
Set<Map.Entry<K,V>> entrySet():获取Map集合中所有的Entry对象'
Entry中获取建和值的方法:
K getKey() :获取此entry对象中的键
V getValue(): 获取此entry对象中的值。
两种遍历方式,一种是keySet,另一种是entrySet。
第一种keySet方式更好,更加简洁,这种是推荐的。
public class Demo02EntrySet {
public static void main(String[] args) {
//创建Map集合
Map<String, String> map = new HashMap<>();
//添加键值对
map.put("it001", "王宝强");
map.put("it002", "李宝强");
map.put("it003", "张宝强");
//使用entrySet的方式遍历这个Map集合
//调用Map集合的entrySet方法获取到Map集合中的所有的Entry对象。
Set<Map.Entry<String, String>> set = map.entrySet();
//遍历存放Entry对象的Set集合,拿到里面的每一个Entry对象。
for (Map.Entry<String, String> entry : set) {
//Entry对象中保存了键值对,我们可以调用方法获取到键和值。
String key = entry.getKey();
String value = entry.getValue();
System.out.println(key + "-" + value);
}
}
}
3、map集合的遍历
如何对Map集合进行遍历。
Map是一个双列集合,不能直接通过增强for或者迭代器去遍历。
我们可以想办法先获取到Map集合中所有的key,把所有的key存放到一个Set集合, 然后遍历这个Set集合,
拿到里面的每一个key, 根据key获取对应的value。
在Map集合中,有一个方法,可以获取到集合中的所有的key
Set<K> keySet(): 获取Map集合中的所有的key,并放入到一个Set集合中返回.
keySet方式遍历的步骤:
1. 调用Map集合的keySet方法,获取所有的key,并存放于一个Set集合中返回
2. 遍历Set集合,拿到Set集合中的每一个key
3. 调用Map集合的get方法,根据key获取对应的value
public class Demo02MapKeySet {
public static void main(String[] args) {
//创建Map集合
Map<String, String> map = new HashMap<>();
//添加
map.put("it001", "刘备");
map.put("it003", "曹操");
map.put("it004", "周瑜");
map.put("it002", "关羽");
//对Map集合进行遍历
//调用Map集合的keySet方法,获取所有的key,并存放于一个Set集合中返回
Set<String> set = map.keySet();
//遍历Set集合,拿到里面的每一个key
for(String key : set) {
//调用Map集合的get方法,根据key获取对应的value
String value = map.get(key);
System.out.println(key + ":" + value);
}
}
}
4、 练习:每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到
map集合中。学生对象作为键, 家庭住址作为值。
注意,学生姓名相同并且年龄相同视为同一名学生
HashMap中的key如何保证唯一性??
HashMap中的key保证唯一性的过程和HashSet一模一样(原因: HashSet内部用的就是一个HashMap)
1. 先比较对象的哈希值
如果对象的哈希值不同,那么肯定是不同的对象。
如果对象的哈希值相同,那么不一定是同一个对象。
2. 如果哈希值相同还要调用equals方法
如果equals方法得到的结果是true,那么表示两个对象相同
如果equals方法得到的结果是false,那么表示两个对象不同。
public class Demo03MapTest {
public static void main(String[] args) {
//定义一个集合,key是Student类型, value是String
Map<Student, String> map = new HashMap<>();
//向Map集合中添加键值对。
map.put(new Student("郭靖", 18), "襄阳");
map.put(new Student("黄蓉", 16), "桃花岛");
map.put(new Student("小龙女", 20), "古墓");
map.put(new Student("小龙女", 20), "龙宫");
//遍历Map集合,拿到Map集合中的每一个键值对并打印
//获取到Map集合中的所有的key,放入到Set集合返回
Set<Student> set = map.keySet();
//遍历这个Set集合,拿到里面的每一个key
for(Student key : set) {
//根据key获取value
String value = map.get(key);
System.out.println(key + "::" + value);
}
}
}
5、LinkedHashMap
LinkedHashMap 也是Map接口的实现类。
内部除了有一个哈希表之外还有一个链表。 链表的作用是保证有序。
LinkedHashMap 它的特点是有序(按照什么顺序存,就按照什么顺序取)
public class Demo04LinkedHashMap {
public static void main(String[] args) {
//创建一个Map集合
Map<String, String> map = new LinkedHashMap<>();
//添加键值对
map.put("it001", "刘备");
map.put("it002", "曹操");
map.put("it003", "孙权");
//进行打印
System.out.println(map);
}
}
在JDK9之后,集合提供了of方法,可以直接创建带有少量元素的集合。
这个of方法是List接口,Set接口,Map接口中的静态方法。
注意:
1. 使用of方法创建的集合不能改变(不能添加或者删除等操作)
2. 这个of方法是ist接口,Set接口,Map接口中的静态方法,不能通过实现类去调用.
public class Demo06Of {
public static void main(String[] args) {
//通过List接口调用of方法,直接创建一个带有少量元素的List集合
List<String> list = List.of("aa", "bb", "cc");
//list.add("dd"); //UnsupportedOperationException
System.out.println("list:" + list);
//通过Set接口调用of方法,直接创建一个带有少量元素的Set集合
Set<String> set = Set.of("张三", "李四", "王叔叔");
System.out.println("set:" + set);
//通过Map接口调用of方法,创建一个带有少量元素的Map集合
Map<String, String> map = Map.of("it001", "张三", "it002", "李四", "it003", "王叔叔");
System.out.println("map:" + map);
}
}
6、bug: 计算机中的问题
debug: 解决问题。
断点作用: 可以让程序在执行的过程中停下来
如何加断点: 在代码的左边点击即可。
如何运行: 右键 debug...
F8: 让代码向下执行一行。
F9: 释放断点
7、斗地主排序版的实现
@SuppressWarnings("all") //注解,抑制警告
public class Demo01Game {
public static void main(String[] args) {
//1. 准备牌
//定义一个ArrayList集合,保存牌的编号
ArrayList<Integer> poker = new ArrayList<>();
//定义一个Map集合,保存编号和牌的对应关系
HashMap<Integer, String> map = new HashMap<>();
//向ArrayList集合添加编号,向Map集合中添加编号和牌的对应关系
//定义两个数组,一个保存花色,一个保存点数
String[] colors = {"♠", "♥", "♣", "♦"};
String[] nums = {"3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K", "A", "2"};
//定义变量,表示牌的编号,从0开始
int index = 0;
//对花色和点数进行组合
for (String num : nums) {
for(String color : colors) {
//先把编号 添加到ArrayList集合
poker.add(index);
//把这个编号和当前遍历到的牌组合添加到map集合中
map.put(index, color + num);
//让编号自增
index++;
}
}
//添加大小王
poker.add(index);
map.put(index, "小王");
index++;
poker.add(index);
map.put(index, "大王");
//2. 洗牌
//打乱保存编号集合的顺序
Collections.shuffle(poker);
//3. 发牌
//定义三个集合,用来保存这三个人的扑克牌(真正保存的是编号)
ArrayList<Integer> playerOne = new ArrayList<>();
ArrayList<Integer> playerTwo = new ArrayList<>();
ArrayList<Integer> playerThree = new ArrayList<>();
//定义一个集合,保存底牌(真正保存的是编号)
ArrayList<Integer> diPai = new ArrayList<>();
//发牌,遍历保存扑克牌的集合,根据每张牌的索引进行发牌。
for(int i = 0; i < poker.size(); i++) {
//拿到当前遍历到的扑克牌(真正遍历到的其实是牌的编号)
Integer card = poker.get(i);
//处理底牌,如果剩余不足三张,就放入到底牌中
if(i >= 51) {
diPai.add(card);
continue;
}
//开始发牌
if(i % 3 == 0) { //根据牌的索引发牌,如果索引 % 3 结果是0,那么就发给第一个人
playerOne.add(card);
} else if(i % 3 == 1) {//如果牌的索引 % 3 结果是1 ,那么就发给第二个人
playerTwo.add(card);
} else { //如果是牌的索引对3取余结果是2,那么就发给第三个人
playerThree.add(card);
}
}
//4. 看牌
lookCard("刘德华", playerOne, map);
lookCard("周润发", playerTwo, map);
lookCard("周星驰", playerThree, map);
lookCard("底牌", diPai, map);
}
/*
看牌方法
参数: String类型的姓名, ArrayList集合(玩家手里的编号), Map集合(编号和牌的对应关系)
*/
public static void lookCard(String name, ArrayList<Integer> list, HashMap<Integer, String> map) {
//对保存编号的ArrayList集合进行排序
Collections.sort(list);
//打印玩家的姓名
System.out.print(name + ": ");
//遍历保存编号的集合,拿到玩家手中的每一个编号
for(Integer num : list) {
//num指的是每张牌的编号
//拿着这个编号去Map集合中找一下这个牌到底是什么
String card = map.get(num);
System.out.print(card + " ");
}
//为了方便后面输出,打印空换行
System.out.println();
}
}
总结:
能够说出Map集合特点
Map集合中的每一个元素都是一个键值对。
键不能重复。
值可以重复。
可以根据键找到对应的值。
使用Map集合添加方法保存数据
map.put(key, value);
如果添加的元素key已经存在了,就会把之前的元素覆盖掉。
使用”键找值”的方式遍历Map集合
keySet方法
1. 调用Map集合的keySet方法,获取所有的key。
2. 遍历保存所有key的Set集合,拿到每一个key。
3. 调用map集合的get方法,根据key获取value
使用”键值对”的方式遍历Map集合
entrySet
1. 调用Map集合的entrySet方法,获取所有的entry对象
2. 遍历保存所有entry对象的Set集合, 拿到每一个Entry
3. 调用entry对象的getKey和getValue获取键和值
能够使用HashMap存储自定义键值对的数据
如果要使用HashMap保存自定义键,并且要保证唯一性,
必须要重写hashCode和equals方法。
能够使用HashMap编写斗地主洗牌发牌案例
因为要排序,所以我们使用了一个集合保存编号。
洗牌发牌操作的都是编号。
只有看牌的时候才根据编号去找的这张牌到底是什么。