Java基础集合篇03-Map集合
Posted bruce1993
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java基础集合篇03-Map集合相关的知识,希望对你有一定的参考价值。
1. Map集合
1.1 Map集合介绍
- Map集合是一个存储数据的容器。
- Map集合存储数据的方式是键值对(key/value)。
- key键不可以重复(若重复设置,则会覆盖原有key对应的值)。
- value值可以重复。
- Map集合的底层数据结构是哈希表(数组+链表/红黑树)。
1.2 Map集合和Collection集合区别
- Collection集合是单例集合
- 元素的种类是单个
- Map集合是双例集合。
- 元素的种类是一对
-
图解:
1.3 Map集合常用子类
- HasMap
- 是Map集合的一个子类
- 底层数据结构是哈希表
- 键不可以重复(键对应的类型需要重写了hashCode()和equals方法()),值可以重复。
- 存取是无序的(存取顺序可能不一致)
- LinkedHashMap
- 是HashMap集合的一个子类
- 底层数据结构是哈希表+链表(记录存取顺序)
- 键不可以重复(键对应的类型需要重写了hashCode()和equals方法()),值可以重复。
- 存取是有序的(存取的顺序一定是一致的)
注意事项:Map接口中的集合都有两个泛型变量,在使用时,要为两个泛型变量赋予数据类型。两个泛型变量的数 据类型可以相同,也可以不同。
1.4 Map接口中常用方法
-
方法
public V put(K key, V value)
: 把指定的键与指定的值添加到Map集合中。public V remove(Object key)
: 把指定的键 所对应的键值对元素 在Map集合中删除,返回被删除元素的值。public V get(Object key)
根据指定的键,在Map集合中获取对应的值。public Set<K> keySet()
: 获取Map集合中所有的键,存储到Set集合中。public Set<Map.Entry<K,V>> entrySet()
: 获取到Map集合中所有的键值对对象的集合(Set集合)。 -
代码
// 创建HashMap对象 HashMap<String,String> hash = new HashMap<>(); // 【添加数据-public V put(K key, V value)】 hash.put("郭靖","华筝"); hash.put("郭靖","黄蓉"); // 会覆盖之前重复的键值对 hash.put("杨过","小龙女"); hash.put("张无忌","赵敏"); hash.put("宋青书","周芷若"); System.out.println(hash); // {杨过=小龙女, 宋青书=周芷若, 郭靖=黄蓉, 张无忌=赵敏} // 【移除数据-public V remove(Object key)】 hash.remove("宋青书"); System.out.println(hash); // {杨过=小龙女, 郭靖=黄蓉, 张无忌=赵敏} // 【根据指定的键获取对应的值-public V get(Object key)】 String value = hash.get("郭靖"); System.out.println(value); // 黄蓉 // 【获取Map集合中所有的键存储到Set集合中-public Set<K> keySet()】 Set<String> set = hash.keySet(); Iterator<String> iterator = set.iterator(); while ((iterator.hasNext())){ String key = iterator.next(); System.out.println(key + "-" + hash.get(key)); } // 【获取Map集合中的Entry对象-public Set<Map.Entry<K,V>> entrySet()】 // Map集合中存储了一组Entry对象,entry对象包装了每一对key/value // Entry对象可以通过getKey()方法获取键,通过getValue方法获取对应的值 Set<Map.Entry<String,String>> set2 = hash.entrySet(); for (Map.Entry<String,String> entry:set2) { System.out.println(entry.getKey() + ‘|‘+entry.getValue()); }
1.5 Map集合中定义自定义类型的键值对
-
注意事项:对应自定义类型的键的类型中需要重新hashCode和equals方法
-
代码:
//【执行类】 public class Main { public static void main(String[] args) { // 存储一组学生信息,要求集合中不允许出现同名同年龄的键 HashMap<Student,Integer> hash = new HashMap<>(); hash.put(new Student("张三",18),10010); hash.put(new Student("张三",18),10086); hash.put(new Student("李四",17),10010); hash.put(new Student("王五",17),10010); System.out.println(hash.size()); // 3个 } } //【学生类】 public class Student { private String name; private int age; public Student() {} public Student(String name, int age) { this.name = name; this.age = age; } public String getName() { return name; } public void setName(String name) { this.name = name; } public int getAge() { return age; } public void setAge(int age) { this.age = age; } @Override public boolean equals(Object o) { if (this == o) return true; if (o == null || getClass() != o.getClass()) return false; Student student = (Student) o; return age == student.age && name.equals(student.name); } @Override public int hashCode() { return Objects.hash(name, age); } }
1.6 LinkedHashMap
-
介绍:是HashMap的子类,存取数据是有序的。
-
代码:
LinkedHashMap<String,String> hash = new LinkedHashMap<>(); hash.put("郭靖","黄蓉"); hash.put("杨过","小龙女"); hash.put("张无忌","赵敏"); hash.put("宋青书","周芷若"); System.out.println(hash);//{郭靖=黄蓉, 杨过=小龙女, 张无忌=赵敏, 宋青书=周芷若}
1.7 Map集合练习
-
需求:计算一个字符串中每个字符出现次数。
-
业务分析:
- 接受用户输入的内容
- 提取每一个字符并统计次数
- 打印统计结果
-
代码:
// 1. 接受用户输入的内容 String text = new Scanner(System.in).next(); // 2. 创建Map集合key存储字符,value存储次数 LinkedHashMap<Character,Integer> hash = new LinkedHashMap<>(); // 3. 循环遍历字符串中的字符,并统计 for(int i = 0; i < text.length();i++) { // 3.1 取出单个字符 char ch = text.charAt(i); // 3.2 检测集合中是否存在这样的键 boolean isHas = hash.containsKey(ch); // 3.3 若存在,则设置key的值次数加1 if(isHas) { int count = hash.get(ch) + 1; hash.put(ch,count); }else {// 否则,则向集合中添加key并设置次数为1 hash.put(ch,1); } } // 4.遍历并打印 // 4.1 获取集合中的键 Set<Character> set = hash.keySet(); // 4.2 遍历 for(Character ch:set){ System.out.println(ch+":" + hash.get(ch)); }
1.8 JDK9对集合添加的优化
-
在创建少量元素的集合时,使用JDK9中提供的静态方法of添加更加合适
-
注意事项:
- of方法只能被接口List、Set、Map接口调用,不能用子类或实现类调用。
- of方法初始化后的集合不能更改。
-
代码:
List<String> list = List.of("张三","李四","王五","赵六"); Set<String> set = Set.of("张三","李四","王五","赵六"); Map<String,Integer> map = Map.of("张三",10,"李四",12); System.out.println(list); // [张三, 李四, 王五, 赵六] System.out.println(set); // [李四, 赵六, 张三, 王五] System.out.println(map); // {张三=10, 李四=12}
1.9 HashTable
-
HashTable集合
- 底层是线程是安全的,单线程,执行速度慢
- 底层数据结构是哈希表
- 之前学习的集合可以存储null键和null值,但是HashTable不可以
-
代码:
HashMap<String,Integer> map = new HashMap<>(); map.put(null,1); map.put("a",null); System.out.println(map); Hashtable<String,Integer> table = new Hashtable<>(); table.put(null,1); // 报错NullPointerException table.put("a",null); System.out.println(table);
2. 模拟斗地主洗牌发牌
-
需求:
- 实现洗牌、发牌、看片、玩家牌排序(从小到大)的功能
-
代码:
public static void main(String[] args) { // 1. 定义Map集合用来装牌 HashMap<Integer,String> map = new HashMap<>(); // 2. 定义数组存放花色 String[]colors={"♥","♠","♣","♦"}; // 3. 定义数组存放牌数字 String[]nums = {"2","A","K","Q","J","10","9","8","7","6","5","4","3"}; // 4. 定义List集合存放牌的索引 ArrayList<Integer> listIndex = new ArrayList<>(); // 5. 定义初始化牌的索引为0 int index = 0; // 添加大小王 map.put(index,"大王"); listIndex.add(index); index++; map.put(index,"小王"); listIndex.add(index); index++; // 6. 组装牌 for (int i = 0; i < nums.length; i++) { for (int i1 = 0; i1 < colors.length; i1++) { listIndex.add(index); map.put( index,colors[i1]+nums[i]); index++; } } // 7.洗牌 Collections.shuffle(listIndex); // 8. 定义玩家牌和底牌集合 ArrayList<Integer> player01ListIndex = new ArrayList<>(); ArrayList<Integer> player02ListIndex = new ArrayList<>(); ArrayList<Integer> player03ListIndex = new ArrayList<>(); ArrayList<Integer> diPai3ListIndex = new ArrayList<>(); // 9. 发牌 for (int i = 0; i < listIndex.size(); i