第二十三天学习笔记:Map集合
1.Map集合(理解)
1.1 Map集合概述和特点
A: 需求: 根据学号获取学生姓名
B:Map接口概述
查看API可以知道:
将键映射到值的对象
一个映射不能包含重复的键
每个键最多只能映射到一个值
C:Map接口和Collection接口的不同
Map是双列的,Collection是单列的
Map的键唯一,Collection的子体系Set是唯一的
Map集合的数据结构针对键有效,跟值无关;Collection集合的数据结构是针对元素有效
public static void main(String[] args) {
//Map集合 就是用来存储 这种 键值映射关系的数据 。 Map 是双列集合
// 一个键只能只能映射一个值,键是唯一的。
//多次存储相同的键,就会发生键相同值覆盖。
//Map集合的数据结构只跟键有关,跟值没关系。
//Collection 单列集合
//存储键是String类型 值是Student类型
//HashMap 键的数据结构是哈希表,键的唯一性,要靠键重写hashCode()和equals()方法才能保证,如果不重写,则无法保证键的唯一性。
//String 类重写hashCode()和equals()方法
HashMap<String, Student> hm = new HashMap<>();
hm.put("s001",new Student("张三",23));
hm.put("s001", new Student("张三", 230));
hm.put("s002", new Student("李四", 24));
hm.put("s003", new Student("王五", 25));
System.out.println(hm.toString());
System.out.println("==========================");
//根据键来删除一对键值对,返回的是,这个键对应的这个值
Student s1 = hm.remove("s004");
System.out.println(hm.toString());
System.out.println(s1);
System.out.println("================================");
boolean remove = hm.remove("s002", new Student("李四", 24));
System.out.println(remove);
}
1.2 Map集合的功能概述(掌握)
A:Map集合的功能概述
a:添加功能
V put(K key,V value):添加元素。这个其实还有另一个功能?替换
如果键是第一次存储,就直接存储元素,返回null
如果键不是第一次存在,就用值把以前的值替换掉,返回以前的值
b:删除功能
void clear():移除所有的键值对元素
V remove(Object key):根据键删除键值对元素,并把值返回
c:判断功能
boolean containsKey(Object key):判断集合是否包含指定的键
boolean containsValue(Object value):判断集合是否包含指定的值
boolean isEmpty():判断集合是否为空
d:获取功能
Set<Map.Entry<K,V>> entrySet(): 返回一个键值对的Set集合
V get(Object key):根据键获取值
Set<K> keySet():获取集合中所有键的集合
Collection<V> values():获取集合中所有值的集合
e:长度功能
int size():返回集合中的键值对的对数
public static void main(String[] args) {
HashMap<Integer, String> hm = new HashMap<>();
hm.put(100,"aaa");
hm.put(200, "bbb");
hm.put(300, "ccc");
hm.put(400, "ddd");
//判断集合中有没有400这个键
boolean b = hm.containsKey(400);
System.out.println(b);
//判断集合中有没有这个值
System.out.println(hm.containsValue("aaa"));
//获取集合的长度
System.out.println(hm.size());
hm.clear();
//判断集合是否为空
System.out.println(hm.isEmpty());
}
1.3 Map集合的基本功能测试(掌握)
A:案例演示
Map集合的基本功能
V put(K key,V value)//键相同 值覆盖
V remove(Object key)
void clear()
boolean containsKey(Object key)
boolean containsValue(Object value)
boolean isEmpty()
int size()
1.4 Map集合的获取功能测试(掌握)
A:案例演示
V get(Object key)
Set<K> keySet()
Collection<V> values()
1.5 Map集合的遍历之键找值(掌握)
A:键找值思路:
获取所有键的集合
遍历键的集合,获取到每一个键
根据键找值
B:案例演示
Map集合的遍历之键找值
public static void main(String[] args) {
//Map 集合的遍历
HashMap<Integer, String> hm = new HashMap<>();
hm.put(100, "aaa");
hm.put(200, "bbb");
hm.put(300, "ccc");
hm.put(400, "ddd");
/* String s = hm.get(100);
System.out.println(s);*/
方式1;通过键找值的方式来遍历
Set<Integer> integers = hm.keySet(); //获取所有的键集
System.out.println(integers);
//遍历键集
for (Integer key : integers) {
//键找值
String value = hm.get(key);
System.out.println(key+"==="+value);
}
}
1.6 Map集合的遍历之键值对对象找键和值(掌握)
A:键值对对象找键和值思路:
获取所有键值对对象的集合
遍历键值对对象的集合,获取到每一个键值对对象
根据键值对对象找键和值
B:案例演示
Map集合的遍历之键值对对象找键和值
public static void main(String[] args) {
//Map 集合的遍历
HashMap<Integer, String> hm = new HashMap<>();
hm.put(100, "aaa");
hm.put(200, "bbb");
hm.put(300, "ccc");
hm.put(400, "ddd");
//遍历方式2:把所有的键值对 对象 全部获取出来
//Entry<Integer, String> 键值对 对象 Node<K,V>、
/* K getKey ()
返回对应于此项的键。
V getValue ()
返回对应于此项的值。*/
Set<Map.Entry<Integer, String>> entries = hm.entrySet();
//遍历键值对集合
for (Map.Entry<Integer, String> node : entries) {
Integer key = node.getKey();
String value = node.getValue();
System.out.println(key+"==="+value);
}
}
1.7 Map集合遍历的两种方式比较图解(理解)
A:画图演示: Map集合遍历的两种方式比较
1.8 HashMap集合键是Stirng值是String的案例(掌握)
HashMap 允许插入null键 null值
A:案例演示: HashMap集合键是Stirng值是String的案例
public static void main(String[] args) {
// HashMap 并允许 null值和 null关键。线程不安全效率高
// Hashtable 不允许存储null值和null键 线程安全效率低
HashMap<Object, Object> hm = new HashMap<>();
hm.put(null,"abc");
hm.put("aaa",null);
hm.put(null,null);
System.out.println(hm);
Hashtable<Object, Object> hashtable = new Hashtable<>();
//hashtable.put("abc",null); 不允许键或者值 为 null
}
1.9 HashMap集合键是String值是Student的案例(掌握)
A:案例演示: HashMap集合键是String值是Student的案例
public static void main(String[] args) {
HashMap<String, Student> hm = new HashMap<>();
hm.put("s001", new Student("张三", 23));
hm.put("s001", new Student("张三", 230));
hm.put("s002", new Student("李四", 24));
hm.put("s003", new Student("王五", 25));
//方式1
Set<String> strings = hm.keySet();
for (String key : strings) {
Student student = hm.get(key);
System.out.println(key+"==="+student.getName()+"=="+student.getAge());
}
System.out.println("==========================");
Set<Map.Entry<String, Student>> entries = hm.entrySet();
for (Map.Entry<String, Student> en : entries) {
String key = en.getKey();
Student student = en.getValue();
System.out.println(key + "===" + student.getName() + "==" + student.getAge());
}
System.out.println("========================");
hm.forEach(new BiConsumer<String, Student>() {
@Override
public void accept(String key, Student student) {
System.out.println(key + "===" + student.getName() + "==" + student.getAge());
}
});
}
1.10 HashMap集合键是Student值是String的案例(掌握)
键唯一 注意重写hashCode方法 和 equals 方法
A:案例演示: HashMap集合键是Student值是String的案例
public static void main(String[] args) {
HashMap<Student, String> hm = new HashMap<>();
hm.put(new Student("张三", 23), "s001");
hm.put(new Student("张三", 23), "s002");
hm.put(new Student("李四", 24), "s003");
hm.put(new Student("王五", 25), "s004");
Set<Student> students = hm.keySet();
for (Student key : students) {
String value = hm.get(key);
System.out.println(key.getName()+"=="+key.getAge()+"=============="+value);
}
System.out.println("============================");
Set<Map.Entry<Student, String>> entries = hm.entrySet();
for (Map.Entry<Student, String> en : entries) {
Student key = en.getKey();
String value = en.getValue();
System.out.println(key.getName() + "==" + key.getAge() + "==============" + value);
}
System.out.println("===============================");
hm.forEach(new BiConsumer<Student, String>() {
@Override
public void accept(Student key, String value) {
System.out.println(key.getName() + "==" + key.getAge() + "==============" + value);
}
});
}
1.11 LinkedHashMap的概述和使用(了解)
A:LinkedHashMap的概述: Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序
B:LinkedHashMap的特点: 底层的数据结构是链表和哈希表 元素有序 并且唯一
元素的有序性由链表数据结构保证 唯一性由 哈希表数据结构保证
Map集合的数据结构只和键有关
C:案例演示: LinkedHashMap的特点
public static void main(String[] args) {
// HashSet
// LinkedHast
// HashMap 键的数据结构是哈希表 保证键唯一,键无序
//LinkedHashMap 键的数据结构链表和哈希表。链表保证了键有序,哈希表保证了键唯一。
LinkedHashMap<Integer, String> hm = new LinkedHashMap<>();
hm.put(100, "aaa");
hm.put(100, "aaa2222");
hm.put(200, "bbb");
hm.put(300, "ccc");
hm.put(400, "ddd");
System.out.println(hm);
}
1.12 TreeMap集合键是String值是String的案例(掌握)
TreeMap 键不允许插入null
A: TreeMap: 键的数据结构是红黑树,可保证键的排序和唯一性
排序分为自然排序和比较器排序
线程是不安全的效率比较高
B:案例演示: TreeMap集合键是Integer值是String的案例
public static void main(String[] args) {
/* A:
TreeMap:
键的数据结构是红黑树, 可保证键的排序和唯一性
排序分为自然排序和比较器排序
线程是不安全的效率比较高*/
//空参构造,就使用的自然排序。
//自然排序,他对键的要求是,要求键实现Comparable接口,重写 compareTo方法,根据此方法的返回值的正负0 来决定键的排列顺序
//Integer 默认实现了Comparable接口
TreeMap<Integer, String> treeMap = new TreeMap<>();
treeMap.put(10,"aaa");
treeMap.put(5, "aaa");
treeMap.put(1, "aaa");
treeMap.put(63, "aaa");
treeMap.put(10, "aaa");
treeMap.put(19, "aaa");
System.out.println(treeMap);
}
1.13 TreeMap集合键是Student值是String的案例(掌握)
A:案例演示: TreeMap集合键是Student值是String的案例
按照年龄大小进行排序
注意键要实现Comparable 接口
public static void main(String[] args) {
//TreeSet 单列集合
//TreeMap
TreeMap<Student, String> hm = new TreeMap<>();
hm.put(new Student("张三", 23), "s002");
hm.put(new Student("李四", 24), "s003");
hm.put(new Student("王五", 25), "s004");
hm.put(new Student("赵六", 20), "s005");
System.out.println(hm);
}
1.14 统计字符串中每个字符出现的次数(理解)
A:案例演示: 需求:统计字符串中每个字符出现的次数
"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
2.集合嵌套
2.1 集合嵌套之HashMap嵌套HashMap(理解)
A:案例演示
集合嵌套之HashMap嵌套HashMap
public static void main(String[] args) {
/* 基础班
张三 20
李四 22
就业班
王五 21
赵六 23
集合嵌套之HashMap嵌套HashMap
*/
Hashtable<String, Integer> jcMap = new Hashtable<>();
jcMap.put("张三",20);
jcMap.put("李四", 22);
Hashtable<String, Integer> jyMap = new Hashtable<>();
jyMap.put("王五", 21);
jyMap.put("赵六", 23);
//创建一个大Map 放两个小Map
HashMap<String, Hashtable<String, Integer>> maxMap = new HashMap<>();
maxMap.put("基础班",jcMap);
maxMap.put("就业班",jyMap);
//遍历集合
Set<Map.Entry<String, Hashtable<String, Integer>>> entries = maxMap.entrySet();
for (Map.Entry<String, Hashtable<String, Integer>> en : entries) {
String key = en.getKey();
System.out.println(key);
Hashtable<String, Integer> minMap = en.getValue();
Set<Map.Entry<String, Integer>> entries1 = minMap.entrySet();
for (Map.Entry<String, Integer> entry : entries1) {
String key1 = entry.getKey();
Integer value = entry.getValue();
System.out.println("\t"+key1+"\t"+value);
}
System.out.println();
}
System.out.println("============================");
Set<String> keySet = maxMap.keySet();
for (String key : keySet) {
System.out.println(key);
Hashtable<String, Integer> minMap = maxMap.get(key);
Set<String> strings = minMap.keySet();
for (String k : strings) {
Integer integer = minMap.get(k);
System.out.println("\t"+k+"\t"+integer);
}
System.out.println();
}
}
2.2集合嵌套之HashMap嵌套ArrayList(理解)
A:案例演示
集合嵌套之HashMap嵌套ArrayList
假设HashMap集合的元素是ArrayList。有3个。
每一个ArrayList集合的值是字符串。
public static void main(String[] args) {
/*
三国演义
吕布
周瑜
笑傲江湖
令狐冲
林平之
神雕侠侣
郭靖
杨过
Map 集合 嵌套List集合
* */
ArrayList<String> sgList = new ArrayList<>();
sgList.add("吕布");
sgList.add("周瑜");
ArrayList<String> xaList = new ArrayList<>();
xaList.add("令狐冲");
xaList.add("林平之");
ArrayList<String> sdList = new ArrayList<>();
sdList.add("郭靖");
sdList.add("杨过");
HashMap<String, ArrayList<String>> bigMap = new HashMap<>();
bigMap.put("三国演义",sgList);
bigMap.put("笑傲江湖", xaList);
bigMap.put("神雕侠侣", sdList);
Set<Map.Entry<String, ArrayList<String>>> entries = bigMap.entrySet();
for (Map.Entry<String, ArrayList<String>> entry : entries) {
String key = entry.getKey();
System.out.println(key);
ArrayList<String> value = entry.getValue();
for (String s : value) {
System.out.println("\t"+s);
}
System.out.println();
}
}
2.3 集合嵌套之ArrayList嵌套HashMap(理解)
A:案例演示
集合嵌套之ArrayList嵌套HashMap
假设ArrayList集合的元素是HashMap。有3个。
每一个HashMap集合的键和值都是字符串。
周瑜---小乔
吕布---貂蝉
郭靖---黄蓉
杨过---小龙女
令狐冲---任盈盈
林平之---岳灵珊
public static void main(String[] args) {
HashMap<String, String> sgMap = new HashMap<>();
sgMap.put("周瑜","小乔");
sgMap.put("吕布", "貂蝉");
HashMap<String, String> sdMap = new HashMap<>();
sdMap.put("郭靖", "黄蓉");
sdMap.put("杨过", "小龙女");
HashMap<String, String> xaMap = new HashMap<>();
xaMap.put("令狐冲", "任盈盈");
xaMap.put("林平之", "岳灵珊");
ArrayList<HashMap<String, String>> bigList = new ArrayList<>();
bigList.add(sgMap);
bigList.add(sdMap);
bigList.add(xaMap);
//遍历
for (HashMap<String, String> hashMap : bigList) {
Set<Map.Entry<String, String>> entries = hashMap.entrySet();
for (Map.Entry<String, String> en : entries) {
String key = en.getKey();
String value = en.getValue();
System.out.println(key+"------"+value);
}
System.out.println();
}
}
3. HashMap和Hashtable的区别(掌握)
A:面试题
HashMap和Hashtable的区别: 查看API可以知道
HashMap: 线程不安全,效率高.允许null值和null键
Hashtable: 线程安全 , 效率低.不允许null值和null键
B:案例演示
HashMap和Hashtable的区别
4. Collections工具类的概述和常见方法讲解(掌握)
A:Collections类概述: 针对集合操作 的工具类
B:Collections成员方法
public static <T> void sort(List<T> list): 排序,默认按照自然顺序
public static <T> int binarySearch(List<?> list,T key): 二分查找
public static <T> T max(Collection<?> coll): 获取最大值
public static void reverse(List<?> list): 反转
public static void shuffle(List<?> list): 随机置换
C:案例演示: Collections工具类的常见方法讲解
5.斗地主代码练习
5.1 模拟斗地主洗牌和发牌(理解) 牌没有排序
5.2 模拟斗地主洗牌和发牌并对牌进行排序的原理图解(理解)
A:画图演示: 画图说明排序原理
5.3 模拟斗地主洗牌和发牌并对牌进行排序的代码实现(理解)
A:案例演示:
public class 斗地主 {
public static void main(String[] args) {
//先得有一副牌
//先创建一个集合充当牌盒子
ArrayList<String> pokerBox = new ArrayList<>();
//生成54张牌放进牌盒子
String[] colors={"♠","♥","♦","♣"};
String[] nums={"A","2","3","4","5","6","7","8","9","10","J","Q","K"};
for (String color : colors) {
for (String num : nums) {
String poker = color.concat(num);
pokerBox.add(poker);
}
}
//手动添加大小王
pokerBox.add("☀");
pokerBox.add("☼");
//洗牌
Collections.shuffle(pokerBox);
Collections.shuffle(pokerBox);
Collections.shuffle(pokerBox);
//发牌:得有三个人来斗地主,还得留三张底牌
ArrayList<String> 星仔 = new ArrayList<>();
ArrayList<String> 刀仔 = new ArrayList<>();
ArrayList<String> 高进 = new ArrayList<>();
ArrayList<String> 底牌 = new ArrayList<>();
//发牌方式1: 一人数个10来张发给你
// 星仔 = (ArrayList<String>) pokerBox.subList(0, 11);
// 方式2:传统发牌 一人一张转着发
//用牌的索引对3取余
/* 星仔 0 3 6 9 余数 0
刀仔 1 4 7 10 余数 1
高进 2 5 8 11 余数 2 */
for (int i = 0; i < pokerBox.size(); i++) {
//留底牌
if(i>=pokerBox.size()-3){
底牌.add(pokerBox.get(i));
}else if(i%3==0){
星仔.add(pokerBox.get(i));
} else if (i % 3 == 1) {
刀仔.add(pokerBox.get(i));
}else{
高进.add(pokerBox.get(i));
}
}
//看牌
lookPoker("星仔",星仔);
lookPoker("刀仔",刀仔);
lookPoker("高进",高进);
lookPoker("底牌",底牌);
}
private static void lookPoker(String name, ArrayList<String> list) {
System.out.println(name);
for (String poker : list) {
System.out.print(poker+"\t");
}
System.out.println();
}
}