第6章 集合框架 - Map接口

优质
小牛编辑
124浏览
2023-12-01

Map接口概述

Map:双列集合类的根接口,用于存储具有键(Key)、值(Value)映射关系的元素,每个元素都包含一对键值,在使用Map集合时可以通过指定的Key找到对应的Value,例如根据一个学生的学号就可以找到对应的学生。Map接口的主要实现类有HashMap和TreeMap。

将键映射到值的对象,一个映射不能包含重复的键,每个键最多只能映射到一个值。其实Map集合中存储的就是键值对。map集合中必须保证键的唯一性。

Map接口和Collection接口的不同

  • Map是双列的,Collection是单列的
  • Map的键唯一,Collection的子体系Set是唯一的
  • Map集合的数据结构值针对键有效,跟值无关
  • Collection集合的数据结构是针对元素有效

Map常用的子类:

  • Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值。
  • Properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合。
  • HashMap:内部结构式哈希表,不是同步的。允许null作为键,null作为值。
  • TreeMap:内部结构式二叉树,不是同步的。可以对Map结合中的键进行排序。
  • HashSet实现Set接口,由哈希表(实际上是一个HashMap实例)支持。

Map接口常用方法

方法声明功能描述
put(K key, V value)有添加和替换功能
putAll(Map m)添加一个Map的元素
clear()清空集合
remove(Object key)根据键删除一个元素
containsKey()判断集合是否包含指定的键
containsValue()判断集合是否包含指定的值
isEmpty()判断集合是否为空
get(Object key)根据键获取值
keySet()获取所有的键
values()获取所有的值
entrySet()获取所有的Entry
size()获取集合元素的个数

HashMap

键是哈希表结构,可以保证键的唯一性

LinkedHashMap

Map 接口的哈希表和链接列表实现,具有可预知的迭代顺序。

TreeMap

键是红黑树结构,可以保证键的排序和唯一性,自然排序,比较器排序。

Map集合遍历

方式1:根据键找值。获取所有键的集合,遍历键的集合,获取到每一个键,根据键找值。

  1. package cn.itcast;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Set;
  5. /*
  6. * Map集合的遍历。
  7. * Map -- 夫妻对
  8. * 思路:
  9. * A:把所有的丈夫给集中起来。
  10. * B:遍历丈夫的集合,获取得到每一个丈夫。
  11. * C:让丈夫去找自己的妻子。
  12. *
  13. * 转换:
  14. * A:获取所有的键
  15. * B:遍历键的集合,获取得到每一个键
  16. * C:根据键去找值
  17. */
  18. public class MapDemo {
  19. public static void main(String[] args) {
  20. // 创建集合对象
  21. Map<String, String> map = new HashMap<String, String>();
  22. // 创建元素并添加到集合
  23. map.put("杨过", "小龙女");
  24. map.put("郭靖", "黄蓉");
  25. map.put("杨康", "穆念慈");
  26. map.put("陈玄风", "梅超风");
  27. // 遍历
  28. // 获取所有的键
  29. Set<String> set = map.keySet();
  30. // 遍历键的集合,获取得到每一个键
  31. for (String key : set) {
  32. // 根据键去找值
  33. String value = map.get(key);
  34. System.out.println(key + "---" + value);
  35. }
  36. }
  37. }

方式2:根据键值对对象找键和值。

  • 获取所有键值对对象的集合
  • 遍历键值对对象的集合,获取到每一个键值对对象
  • 根据键值对对象找键和值
  1. package cn.itcast;
  2. import java.util.HashMap;
  3. import java.util.Map;
  4. import java.util.Set;
  5. /*
  6. * Map集合的遍历。
  7. * Map -- 夫妻对
  8. *
  9. * 思路:
  10. * A:获取所有结婚证的集合
  11. * B:遍历结婚证的集合,得到每一个结婚证
  12. * C:根据结婚证获取丈夫和妻子
  13. *
  14. * 转换:
  15. * A:获取所有键值对对象的集合
  16. * B:遍历键值对对象的集合,得到每一个键值对对象
  17. * C:根据键值对对象获取键和值
  18. *
  19. * 这里面最麻烦的就是键值对对象如何表示呢?
  20. * 看看我们开始的一个方法:
  21. * Set<Map.Entry<K,V>> entrySet():返回的是键值对对象的集合
  22. */
  23. public class MapDemo {
  24. public static void main(String[] args) {
  25. // 创建集合对象
  26. Map<String, String> map = new HashMap<String, String>();
  27. // 创建元素并添加到集合
  28. map.put("杨过", "小龙女");
  29. map.put("郭靖", "黄蓉");
  30. map.put("杨康", "穆念慈");
  31. map.put("陈玄风", "梅超风");
  32. // 获取所有键值对对象的集合
  33. Set<Map.Entry<String, String>> set = map.entrySet();
  34. // 遍历键值对对象的集合,得到每一个键值对对象
  35. for (Map.Entry<String, String> me : set) {
  36. // 根据键值对对象获取键和值
  37. String key = me.getKey();
  38. String value = me.getValue();
  39. System.out.println(key + "---" + value);
  40. }
  41. }
  42. }

Map集合的应用及扩展

  1. package cn.itcast;
  2. import java.util.Scanner;
  3. import java.util.Set;
  4. import java.util.TreeMap;
  5. /*
  6. * 需求 :"aababcabcdabcde",获取字符串中每一个字母出现的次数要求结果:a(5)b(4)c(3)d(2)e(1)
  7. *
  8. * 分析:
  9. * A:定义一个字符串(可以改进为键盘录入)
  10. * B:定义一个TreeMap集合
  11. * 键:Character
  12. * 值:Integer
  13. * C:把字符串转换为字符数组
  14. * D:遍历字符数组,得到每一个字符
  15. * E:拿刚才得到的字符作为键到集合中去找值,看返回值
  16. * 是null:说明该键不存在,就把该字符作为键,1作为值存储
  17. * 不是null:说明该键存在,就把值加1,然后重写存储该键和值
  18. * F:定义字符串缓冲区变量
  19. * G:遍历集合,得到键和值,进行按照要求拼接
  20. * H:把字符串缓冲区转换为字符串输出
  21. *
  22. * 录入:linqingxia
  23. * 结果:result:a(1)g(1)i(3)l(1)n(2)q(1)x(1)
  24. */
  25. public class TreeMapDemo {
  26. public static void main(String[] args) {
  27. // 定义一个字符串(可以改进为键盘录入)
  28. Scanner sc = new Scanner(System.in);
  29. System.out.println("请输入一个字符串:");
  30. String line = sc.nextLine();
  31. // 定义一个TreeMap集合
  32. TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>();
  33. // 把字符串转换为字符数组
  34. char[] chs = line.toCharArray();
  35. // 遍历字符数组,得到每一个字符
  36. for (char ch : chs) {
  37. // 拿刚才得到的字符作为键到集合中去找值,看返回值
  38. Integer i = tm.get(ch);
  39. // 是null:说明该键不存在,就把该字符作为键,1作为值存储
  40. if (i == null) {
  41. tm.put(ch, 1);
  42. } else {
  43. // 不是null:说明该键存在,就把值加1,然后重写存储该键和值
  44. i++;
  45. tm.put(ch, i);
  46. }
  47. }
  48. // 定义字符串缓冲区变量
  49. StringBuilder sb = new StringBuilder();
  50. // 遍历集合,得到键和值,进行按照要求拼接
  51. Set<Character> set = tm.keySet();
  52. for (Character key : set) {
  53. Integer value = tm.get(key);
  54. sb.append(key).append("(").append(value).append(")");
  55. }
  56. // 把字符串缓冲区转换为字符串输出
  57. String result = sb.toString();
  58. System.out.println("result:" + result);
  59. }
  60. }

示例2:在很多项目中,应用比较多的是一对多的映射关系,这就可以通过嵌套的形式将多个映射定义到一个大的集合中,并将大的集合分级处理,形成一个体系。

  1. package cn.itcast;
  2. import java.util.ArrayList;
  3. import java.util.HashMap;
  4. import java.util.Set;
  5. class Student {
  6. private String name;
  7. private int age;
  8. public Student() {
  9. super();
  10. }
  11. public Student(String name, int age) {
  12. super();
  13. this.name = name;
  14. this.age = age;
  15. }
  16. public String getName() {
  17. return name;
  18. }
  19. public void setName(String name) {
  20. this.name = name;
  21. }
  22. public int getAge() {
  23. return age;
  24. }
  25. public void setAge(int age) {
  26. this.age = age;
  27. }
  28. }
  29. /*
  30. * 黑马程序员
  31. * bj 北京校区
  32. * jc 基础班
  33. * 林青霞 27
  34. * 风清扬 30
  35. * jy 就业班
  36. * 赵雅芝 28
  37. * 武鑫 29
  38. * sh 上海校区
  39. * jc 基础班
  40. * 郭美美 20
  41. * 犀利哥 22
  42. * jy 就业班
  43. * 罗玉凤 21
  44. * 马征 23
  45. * gz 广州校区
  46. * jc 基础班
  47. * 王力宏 30
  48. * 李静磊 32
  49. * jy 就业班
  50. * 郎朗 31
  51. * 柳岩 33
  52. * xa 西安校区
  53. * jc 基础班
  54. * 范冰冰 27
  55. * 刘意 30
  56. * jy 就业班
  57. * 李冰冰 28
  58. * 张志豪 29
  59. */
  60. public class HashMapDemo {
  61. public static void main(String[] args) {
  62. // 创建大集合
  63. HashMap<String, HashMap<String, ArrayList<Student>>> czbkMap = new HashMap<String, HashMap<String, ArrayList<Student>>>();
  64. // 北京校区数据
  65. HashMap<String, ArrayList<Student>> bjCzbkMap = new HashMap<String, ArrayList<Student>>();
  66. ArrayList<Student> array1 = new ArrayList<Student>();
  67. Student s1 = new Student("林青霞", 27);
  68. Student s2 = new Student("风清扬", 30);
  69. array1.add(s1);
  70. array1.add(s2);
  71. ArrayList<Student> array2 = new ArrayList<Student>();
  72. Student s3 = new Student("赵雅芝", 28);
  73. Student s4 = new Student("武鑫", 29);
  74. array2.add(s3);
  75. array2.add(s4);
  76. bjCzbkMap.put("基础班", array1);
  77. bjCzbkMap.put("就业班", array2);
  78. czbkMap.put("北京校区", bjCzbkMap);
  79. // 西安校区数据
  80. HashMap<String, ArrayList<Student>> xaCzbkMap = new HashMap<String, ArrayList<Student>>();
  81. ArrayList<Student> array3 = new ArrayList<Student>();
  82. Student s5 = new Student("范冰冰", 27);
  83. Student s6 = new Student("刘意", 30);
  84. array3.add(s5);
  85. array3.add(s6);
  86. ArrayList<Student> array4 = new ArrayList<Student>();
  87. Student s7 = new Student("李冰冰", 28);
  88. Student s8 = new Student("张志豪", 29);
  89. array4.add(s7);
  90. array4.add(s8);
  91. xaCzbkMap.put("基础班", array3);
  92. xaCzbkMap.put("就业班", array4);
  93. czbkMap.put("西安校区", xaCzbkMap);
  94. // 遍历集合
  95. Set<String> czbkMapSet = czbkMap.keySet();
  96. for (String czbkMapKey : czbkMapSet) {
  97. System.out.println(czbkMapKey);
  98. HashMap<String, ArrayList<Student>> czbkMapValue = czbkMap
  99. .get(czbkMapKey);
  100. Set<String> czbkMapValueSet = czbkMapValue.keySet();
  101. for (String czbkMapValueKey : czbkMapValueSet) {
  102. System.out.println("\t" + czbkMapValueKey);
  103. ArrayList<Student> czbkMapValueValue = czbkMapValue
  104. .get(czbkMapValueKey);
  105. for (Student s : czbkMapValueValue) {
  106. System.out.println("\t\t" + s.getName() + "---"
  107. + s.getAge());
  108. }
  109. }
  110. }
  111. }
  112. }

运行结果: