Map集合
java.util.Map<k,v>集合
▶ Map接口下的集合与Collection接口下的集合的存储数据的形式不同
编辑
▶ Map集合的特点:
(1)Map集合是一个双列集合,一个元素包含两个值(一个key,一个value)
(2)Map集合中的元素,key和value的数据类型可以相同也可以不同
(3)Map集合中的元素,key是不允许重复的,value是可以重复的
(4)Map集合中的元素,key和value是一一对应的
【 这里的Map集合和python中的字典很像】
▶ Map接口最常用的两个实现类 --- HashMap 和 LinkedHashMap
java.util.HashMap<k , v>集合 implements Map<k, v>接口
HashMap集合的特点:
(1)HashMap集合底层是哈希表:查询速度非常快
JDK1.8 之前:数组+单向链表
JDK1.8 之后:数组+单向链表/红黑树(链表长度超过8):提高查询速度
(2)HashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致
java.util.LinkedHashMap<k, v>集合 extends HashMap<k, v>集合
LinkedHashMap的特点:
(1)LinkedHashMap集合底层是哈希表+链表(链表的作用是保证迭代的顺序)
(2)LinkedHashMap集合是一个有序集合,存储元素和取出元素的顺序是一致的
▶ Map接口中的常用方法
--- public V put(K key ,V value) :把指定的键与指定的值添加到Map集合中
返回值V:存储键值对的时候,key不重复,返回值v是null
存储键值对的时候,key重复,会使用新的value替换map中重复的value,返回被替换的value值
编辑
--- public V remove(Object key) :把指定的键所对应的键值对元素在Map集合中删除,返回被删除元素的值
返回值V:key存在,v返回被删除的值
key不存在,v返回null
编辑
--- public V get(Object key) :根据指定的键在Map集合中获取对应的值
返回值:key存在,v返回对应的value值
key不存在,v返回null
编辑
--- boolean containsKey(Object key) :判断集合中是否包含指定的键
返回值:包含指定的键返回true,不包含指定的键返回false
编辑
▶ Entry 键值对对象
Map中存放的是两种对象,一种称为key(键),一种称为value(值),它们在Map中是一一对应的关系,这一对对象又称做Map中的一个Entry(项)。
Entry将键值对的对应关系封装成了对象,即键值对对象,这样我们在遍历Map集合时就可以从每一个键值对(Entry)对象中获取对应的键与对应的值。
Entry表示一对键和值,也提供了获取对应键和对应值的方法:
--- public K getKey() :获取Entry对象中的键
--- public V getValue() :获取Entry对象中的值
Map集合中也提供了获取所有Entry对象的方法:
--- public Set<Map.Entry<K,V>> entrySet() :获取到Map集合中所有的键值对对象的集合(Set集合)
▶ Map集合的遍历方式
1. 通过键找值的方式
Map集合中的方法:Set<K> keySet() --- 返回此映射中包含的键的Set视图
实现步骤:
(1)使用Map集合中的方法keySet(),把Map集合所有的key取出来,存储到一个Set集合中
(2)遍历Set,获取Map集合中的每一个key
(3)通过Map集合中的方法get(key),通过key找到value
编辑
2. 通过Entry对象遍历
Map集合中的方法:public Set<Map.Entry<K,V>> entrySet() 返回此映射中包含的映射关系的Set视图
实现步骤:
(1)使用Map集合中的方法entrySet() ,把Map集合中多个Entry对象取出来,存储到一个Set集合中
(2)遍历Set集合,获取每一个Entry对象
(3)使用Entry对象中的方法getKey() 和 getValue()获取键与值
编辑
▶ HashMap存储自定义类型键值
编辑
▶ LinkedHashMap集合
java.util.LinkedHashMap<K,V> extends HashMap<K,V>
Map接口的哈希表和链接列表实现,具有可预知的迭代顺序
底层原理: 哈希表+链表(记录元素的顺序)
编辑
运行结果: 编辑
▶ Hashtable集合
java.util.Hashtable<K,V>集合 implements Map<K,V>接口
Hashtable:底层也是一个哈希表,是一个线程安全的集合,是单线程集合,速度慢
HashMap:底层是一个哈希表,是一个线程不安全的集合,是多线程的集合,速度快
HashMap集合可以存储null值,null键(之前学的所有的集合都可以)
Hashtable集合不能存储null值,null键
Hashtable 和 Vector集合一样,在jdk1.2版本之后被更加先进的集合(HashMap,ArrayList)取代了
Hashtable 的子类Properties依然活跃在历史舞台
Properties集合是一个唯一和IO流相结合的集合
Map集合练习
题目:计算一个字符串中每个字符出现的次数
分析:
1. 使用Scanner获取用户输入的一个字符串
2. 遍历字符串,获取每一个字符
(1)String类的方法toCharArray,把字符串转换为一个字符数组,遍历数组
(2)String类的方法length()+charAt(索引)
3. 使用Map集合中的方法判断获取到的字符是否存储在Map集合中
(1)使用Map集合中的方法containsKey(获取到的字符),返回的是boolean值
true:字符存在
通过字符(key)获取value(统计个数)
把value++
再把新的value存储到Map集合中
false:字符不存在
把字符作为key,1作为value存储到Map集合中
(2)使用Map集合的get(key)
返回null,key不存在
返回的不是null,key存在
代码:
编辑
JDK9对集合添加的优化
编辑
Debug追踪
Debug调试程序: 可以让代码逐行执行,查看代码执行的过程,调试程序中出现的bug
使用方式:
(1)在行号的右边,鼠标左键单击,添加断点(每个方法的第一行(新手),哪里有bug添加到哪里(以后))
(2)右键选择Debug执行程序,程序就会停留在添加的第一个断点处
斗地主综合案例(双列)
编辑
【 注:图中的soft写错了,应该是sort方法排序 】
import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; /* 斗地主综合案例:有序版本 1. 准备牌 2. 洗牌 3. 发牌 4. 排序 5. 看牌 */ public class DouDiZhu { public static void main(String[] args) { /*准备牌: 创建Map集合,存储牌的索引和组装好的牌 创建一个List集合,存储牌的索引 */ HashMap<Integer,String> poker = new HashMap<>() ; ArrayList<Integer> pokerIndex = new ArrayList<>() ; List<String> colors = List.of("♠","♥","♣","♦"); List<String> numbers = List.of("2","A","K","Q","J","10","9","8","7","6","5","4","3"); // 把大王小王存储到集合中 // 定义一个牌的索引 int index = 0; poker.put(index,"大王"); pokerIndex.add(index); index++; poker.put(index,"小王"); pokerIndex.add(index); index++; // 循环嵌套遍历两个集合组装52张牌,存储到集合中 for(String number:numbers) { for(String color:colors) { poker.put(index,color+number); pokerIndex.add(index); index++; } } //System.out.println(poker); //System.out.println(pokerIndex); /* 2.洗牌 使用Collections中的方法shuffle(List) */ Collections.shuffle(pokerIndex); /* 3.发牌 定义4个集合,存储玩家牌的索引和底牌的索引 */ ArrayList<Integer> player1 = new ArrayList<>(); ArrayList<Integer> player2 = new ArrayList<>(); ArrayList<Integer> player3 = new ArrayList<>(); ArrayList<Integer> dipai = new ArrayList<>(); // 遍历存储索引的List集合,获取每一个牌的索引 for(int i=0;i<pokerIndex.size();i++) { Integer in = pokerIndex.get(i); // 先判断底牌 if(i>=51) { // 给底牌发牌 dipai.add(in); }else if(i%3==0) { // 给玩家1发牌 player1.add(in); }else if(i%3==1) { // 给玩家2发牌 player2.add(in); }else if(i%3==2) { // 给玩家3发牌 player3.add(in); } } /* 4.排序 使用Collections中的方法sort(list) 默认是升序排序 */ Collections.sort(player1); Collections.sort(player2); Collections.sort(player3); Collections.sort(dipai); /* 5.看牌 调用看牌的方法 */ lookPoker("刘德华",poker,player1); lookPoker("周润发",poker,player2); lookPoker("古天乐",poker,player3); lookPoker("底牌",poker,dipai); } /* 定义一个看牌的方法,提高代码的复用性 参数: String name :玩家名称 HashMap<Integer,String> poker:存储牌的poker集合 ArrayList<Integer> list:存储玩家和底牌的list集合 查表法: 遍历玩家或者底牌集合,获取牌的索引 使用牌的索引去Map集合中,找到对应的牌 */ public static void lookPoker(String name, HashMap<Integer,String> poker,ArrayList<Integer> list) { // 输出玩家的名称,不换行 System.out.print(name+":"); // 遍历玩家或者底牌集合,获取牌的索引 for(Integer key:list) { // 使用牌的索引,去Map集合中找到对应的牌 String value = poker.get(key); System.out.print(value+" "); } System.out.println(); } }