Java集合-Map集合体系概述
文章目录
- 一、Map集合
- 1. Map集合概述
- 2. Map集合的功能
- 3. Map集合的两种遍历方式
- 二、Map集合体系下的三个集合
- 1. HashMap
- 2. LinkedHashMap
- 3. TreeMap
- 4. 集合嵌套
- 5. HashMap与Hashtable的区别
- 6. 例题:模拟斗地主进行洗牌发牌
一、Map集合
1. Map集合概述
- 为什么要有Map集合
- 在Collection集合体系中,我们每次只能存储一个元素,但是遇到像学生的学号与姓名、身份证号与姓名等信息时,无法将两个信息联系起来,两个信息是分开存储的
- Map集合的特点
- Map集合是双列的,存储数据时是成对存储的,将其中一个作为键,另一个作为值,键与值是映射的关系。一个键只能对应一个值,也就是Map集合中键是唯一的,不能重复。
- Map集合的数据结构只与键有关,与值无关
- Map集合体系与Collection集合体系的不同
- Map集合是双列的,元素成对存储;Collection集合是单列的,元素单个存储
- Map集合的键不能重复,Collection集合的Set分支的元素是唯一的
- Map集合的数据结构只针对键有效,与值无关;Collection集合的数据结构是针对值的
2. Map集合的功能
- 添加功能
- V put(K key,V value)
- 向Map集合中添加一个键值对,如果添加的键集合中已有,则用新键的值覆盖旧键的值
- 如果是第一次添加该键,则返回null,否则返回该键对应的旧值
- V put(K key,V value)
- 删除功能
- void clear()
- 删除集合中的所有键值对
- V remove(Object key)
- 删除指定键对应的键值对,并将值返回
- boolean containsKey(Object key)
- 判断集合是否包含指定的键
- boolean containsValue(Object value)
- 判断集合是否包含指定的值
- boolean isEmpty()
- 判断集合是否为空
- void clear()
- 获取功能
- Set<Map.Entry<K,V>> entrySet()
- 将指定的集合拆分成键值对形式,并将键值对集合返回
- V get(Object key)
- 得到指定键对应的值
- Set keySet()
- 得到集合中所有键的集合
- Collection values()
- 得到集合中所有值的集合
- Set<Map.Entry<K,V>> entrySet()
- 集合长度
- int size()
- 返回结合中键值对的数量
- int size()
3. Map集合的两种遍历方式
- 根据键找值
- 先通过keySet方法得到集合中所有的键的集合
- 遍历键的集合
- 通过get方法找到键对应的值
- 根据键值对找值
- 先通过entrySet方法得到所有键值对的集合
- 遍历键值对集合
- 通过getKey方法得到键,通过getVaule方法得到值
二、Map集合体系下的三个集合
1. HashMap
- 特点
- 底层用哈希表实现
- 允许插入null键与null值
- 键值唯一,但存取顺序不一致
- 注意
- 如果键是自定义对象需要重写hashcode方法与equals方法
2. LinkedHashMap
- 特点
- 底层用使用哈希表与链表实现
- 元素唯一,有序
3. TreeMap
- 特点
- 数据结构是红黑树
- 元素唯一,且能按照给定的规则排序
- 线程安全,但效率高
- 练习
- 统计字符串中每个字符出现的次数
public class StatiNums {//统计一个字符串中每个字符出现的次数public static void main(String[] args) {String str = "asdasdfasdadsasddsdasdaasdasd";HashMap<Character, Integer> hashMap = new HashMap<>();//定义HashMap集合char[] arrs = str.toCharArray();//将字符串转换为字符数组for (char ch : arrs) {hashMap.put(ch, (!hashMap.containsKey(ch)) ? 1 : (hashMap.get(ch) + 1));//当包含的时候给值加一}for (Character key : hashMap.keySet()) {//遍历哈希表,输出键和值System.out.println(key + ":" + hashMap.get(key));}}
}
//运行结果
//a:9
//s:9
//d:10
//f:1
4. 集合嵌套
-
打印如下所示图形文字
传智播客
就业班
王五 20
赵六 20
基础班
张三 20
李四 20- 代码示例
public class MyTest {//完成集合嵌套,并遍历public static void main(String[] args) {/*** 集合的嵌套*/HashMap<String, ArrayList> totalHashMap = new HashMap<>();//定义HashMap集合ArrayList<Student> basicList = new ArrayList<>();//定义基础班列表basicList.add(new Student("张三", 20));basicList.add(new Student("李四", 20));ArrayList<Student> employeeList = new ArrayList<>();//定义就业班列表employeeList.add(new Student("王五", 20));employeeList.add(new Student("赵六", 20));totalHashMap.put("基础班", basicList);//将基础班列表存放进HashMap集合中totalHashMap.put("就业班", employeeList);//将就业班列表存放进HashMap集合中HashMap<String, HashMap> finalHashSet = new HashMap<>();//定义最终的集合finalHashSet.put("传智播客", totalHashMap);//将HashMap集合totalHashMap放进最终的集合中/*** 遍历方法一,使用键的集合遍历*/for (String s : finalHashSet.keySet()) {//得到所有的键并遍历System.out.println(s);//打印键totalHashMap = finalHashSet.get(s);//得到键对应的值Set<String> keys = totalHashMap.keySet();//先得到所有的键,根据键去遍历集合,取出元素for (String key : keys) {System.out.println("\t"+key);ArrayList list = totalHashMap.get(key);for (Object o : list) {Student stu = (Student) o;System.out.println("\t\t" + stu.getName() + "\t\t" + stu.getAge());}}}}
}
//运行结果
// 传智播客
// 就业班
// 王五 20
// 赵六 20
// 基础班
// 张三 20
// 李四 20
5. HashMap与Hashtable的区别
- HashMap线程不安全,效率高,允许null键与null值
- Hashtable线程安全,效率低,不允许null键与null值
6. 例题:模拟斗地主进行洗牌发牌
- 模拟斗地主进行洗牌发牌
- public static void shuffle(List<?> list)
- Collections类中的一个方法,能够将Collection集合体系中的元素随机打乱
- 代码
- public static void shuffle(List<?> list)
public class PokerGame {//完成模拟斗地主案例public static void main(String[] args) {/*** 1.创建牌盒子与索引器*/String[] color = {"♥", "♠", "♦", "♣"};String[] value = {"A", "2", "3", "4", "5", "6", "7", "8", "9", "10", "J", "Q", "K"};int index = 1;HashMap<Integer, String> pokerBox = new HashMap<>();//牌盒子,存储54张牌ArrayList<Integer> indexs = new ArrayList<>();//索引,用来洗牌和发牌/*** 2.给牌盒子与索引器内填充数据*/for (int j = 0; j < value.length; j++) {//外层是面值for (int i = 0; i < color.length; i++) {//里层是花色,将同一面值的牌放在一起pokerBox.put(index, color[i].concat(value[j]));indexs.add(index);index++;}}pokerBox.put(index, "🃏");indexs.add(index);pokerBox.put(++index, "🃏");indexs.add(index);//手动添加大小王/*** 3.洗牌*/Collections.shuffle(indexs);/*** 4.发牌(平民1,平民2,地主,底牌)*/TreeMap<Integer, String> 平民1 = new TreeMap<>();TreeMap<Integer, String> 平民2 = new TreeMap<>();TreeMap<Integer, String> 地主 = new TreeMap<>();TreeMap<Integer, String> 底牌 = new TreeMap<>();//indexs.get(i)是得到索引器中存储的索引//pokerBox.get(indexs.get(i))是得到牌盒子中对应索引的牌for (int i = 0; i < indexs.size(); i++) {if (i < 3) {底牌.put(indexs.get(i), pokerBox.get(indexs.get(i)));} else if (i % 3 == 0) {平民1.put(indexs.get(i), pokerBox.get(indexs.get(i)));} else if (i % 3 == 1) {平民2.put(indexs.get(i), pokerBox.get(indexs.get(i)));} else if (i % 3 == 2) {地主.put(indexs.get(i), pokerBox.get(indexs.get(i)));}}/*** 5.看牌*/showPoker(地主, "地主");showPoker(平民1, "平民1");showPoker(平民2, "平民2");showPoker(底牌, "底牌");}/*** 得到传入TreeMap对象(玩家的牌)的值*/private static void showPoker(TreeMap<Integer, String> map, String name) {System.out.print(name + ":\t");for (Integer key : map.keySet()) {System.out.print(map.get(key) + "\t");}System.out.println();}
}
//运行结果:
//地主: ♥A ♣A ♥2 ♥3 ♠4 ♥5 ♦5 ♣5 ♠6 ♥7 ♥9 ♥J ♠J ♦J ♦Q ♥K ♠K
//平民1: ♠A ♦2 ♣2 ♠3 ♦3 ♣3 ♥6 ♦6 ♣6 ♣7 ♦8 ♣8 ♠9 ♣10 ♥Q ♣Q ♣K
//平民2: ♦A ♠2 ♥4 ♦4 ♣4 ♠5 ♦7 ♥8 ♠8 ♦9 ♣9 ♥10 ♣J ♠Q ♦K 🃏 🃏
//底牌: ♠7 ♠10 ♦10
发布评论