java进阶——day04-1 Map
Map集合
概述
Collection中的集合:元素是孤立存在的(理解为单身),向集合存储元素采用一个个元素的存储方式
Map中的集合:元素是成对存在的(理解为夫妻),每个元素由键和值两部分组成,通过键能找到对应的值。
Collection中的集合称为单列集合
Map中的集合称为双列集合
注意:
Map集合不能包含重复的键(key唯一),但是值(value不唯一)可以重复;每个键只能对应一个值。

Map常用子类---HashMap
1.HashMap集合底层是哈希表,查询速度特别快
JDK1.8前:数组+单向链表
JDK1.8后:数组+单向链表/红黑树(链表长度>8采用红黑树,提高查询速度)
2.HashMap集合是一个无序集合,存储和取出元素的顺序可能不一致
2、LinkedHashMap
1.LinkedHashMap集合底层是哈希表+链表(包证迭代的顺序)
2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的
3、注意
HashMap&LinkedHashMap:由于要保证键的唯一性,需要重写hashCode()方法和equals()方法
Map接口中的集合都有两个泛型变量,在使用时,要为两个泛型变量赋予数据类型。两个变量的数据类型可以相同也可以不同。
Map接口中的常用方法
public V put(K key, V value) : 把指定的键与指定的值添加到Map集合中。
package day04; import java.util.HashMap; public class Map_method { public static void main(String[] args) { //创建Map对象——hashMap //此处 两个泛型变量都为String类型 HashMap<String,String> map = new HashMap<>(); //往Map中添加键值对 map.put("陈易安","曾勇"); map.put("胡一菲","曾小贤"); map.put("关谷神奇","唐悠悠"); System.out.println(map);//{陈易安=曾勇, 胡一菲=曾小贤, 关谷神奇=唐悠悠} } }
public V remove(Object key) : 把指定的键(key)所对应的键值(vlaue)元素 在Map集合中删除,返回被删除元素的值。
package day04; import java.util.HashMap; public class Map_method { public static void main(String[] args) { //创建Map对象——hashMap //此处 两个泛型变量都为String类型 HashMap<String,String> map = new HashMap<>(); //往Map中添加键值对 map.put("陈易安","曾勇"); map.put("胡一菲","曾小贤"); map.put("关谷神奇","唐悠悠"); System.out.println(map);//{陈易安=曾勇, 胡一菲=曾小贤, 关谷神奇=唐悠悠} String re = map.remove("关谷神奇"); System.out.println(re);//唐悠悠 System.out.println(map);//{陈易安=曾勇, 胡一菲=曾小贤} } }
public V get(Object key): 根据指定的键(Key),在Map集合中获取对应的值(Value)。
package day04; import java.util.HashMap; public class Map_method { public static void main(String[] args) { //创建Map对象——hashMap //此处 两个泛型变量都为String类型 HashMap<String,String> map = new HashMap<>(); //往Map中添加键值对 map.put("陈易安","曾勇"); map.put("胡一菲","曾小贤"); map.put("关谷神奇","唐悠悠"); System.out.println(map);//{陈易安=曾勇, 胡一菲=曾小贤, 关谷神奇=唐悠悠} String user = map.get("陈易安"); System.out.println(user);//曾勇 } }
public Set<K> keySet() : 获取Map集合中所有的键,存储到Set集合中
package day04; import java.util.HashMap; import java.util.Set; public class Map_method { public static void main(String[] args) { //创建Map对象——hashMap //此处 两个泛型变量都为String类型 HashMap<String,String> map = new HashMap<>(); //往Map中添加键值对 map.put("陈易安","曾勇"); map.put("胡一菲","曾小贤"); map.put("关谷神奇","唐悠悠"); System.out.println(map);//{陈易安=曾勇, 胡一菲=曾小贤, 关谷神奇=唐悠悠} //定义String类 来接收key 因为key也是String类型 Set<String> strings = map.keySet(); for (String s:strings ) { System.out.print(s+" ");//陈易安 胡一菲 关谷神奇 } } }
public Set<Map.Entry<K,V>> entrySet() : 获取到Map集合中所有的 键值对对象 的集合(Set集合)。
作用解析:当Map集合一创建,就会在Map集合中创建一个Entry对象,用来记录键与值---->证明(结婚证)
package day04; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Map_method { public static void main(String[] args) { //创建Map对象——hashMap //此处 两个泛型变量都为String类型 HashMap<String,String> map = new HashMap<>(); //往Map中添加键值对 map.put("陈易安","曾勇"); map.put("胡一菲","曾小贤"); map.put("关谷神奇","唐悠悠"); System.out.println(map);//{陈易安=曾勇, 胡一菲=曾小贤, 关谷神奇=唐悠悠} Set<Map.Entry<String, String>> entries = map.entrySet(); System.out.println(entries);//[陈易安=曾勇, 胡一菲=曾小贤, 关谷神奇=唐悠悠] } }

Map集合遍历Key找Vlaue的方法
Map中存放的是两种对象,分别为键(Key)与 值(Value)他们是一一对应的关系。而在Map集合创建时,会由Entry记录,所以我们可以通过Entry提供的获取键和值的方法来遍历。
获取Entry对象的键:
public K getKey()
获取Entry对象的值:
public V getValue();
在Map集合中也提供了获取所有Entry对象的方法
public Set<Map.Entry<K,V>> entrySet():获取Map集合中所有键值对对象的集合(Set集合)
例如:
package day04; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Map_Entry { public static void main(String[] args) { //创建hashMap对象 Map<Integer,String> Student = new HashMap<>(); //添加元素到hashMap对象中 Student.put(1,"刘昊然"); Student.put(2,"张子枫"); Student.put(3,"欧阳娜娜"); //利用Map 的 SetEntry获取所有键值对对象(SetEntry获得的集合是Set集合) Set<Map.Entry<Integer, String>> st = Student.entrySet(); //我们利用Set集合的迭代器遍历键值对对象 Iterator<Map.Entry<Integer, String>> it = st.iterator(); while (it.hasNext()){ //创建Entry对象 接收Entry对象 Map.Entry<Integer,String> getEKV = it.next(); //通过getKey()和getValue() 分别获取键值 int key = getEKV.getKey(); String vlaue = getEKV.getValue(); System.out.println("学号为"+key+"的学生,叫做:"+vlaue); /** * 学号为1的学生,叫做:刘昊然 * 学号为2的学生,叫做:张子枫 * 学号为3的学生,叫做:欧阳娜娜 */ } } }
注意(重点):
Map集合不能直接使用迭代器或者foreach进行遍历,但是转成Set集合就可以使用了。
package day04; import java.security.Key; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class Map_method { public static void main(String[] args) { //创建Map对象——hashMap //此处 两个泛型变量都为String类型 HashMap<String,String> map = new HashMap<>(); //往Map中添加键值对 map.put("陈易安","曾勇"); map.put("胡一菲","曾小贤"); map.put("关谷神奇","唐悠悠"); //通过Map的SetEntry方法 获取Map中的键值对对象 Set<Map.Entry<String, String>> entrySet = map.entrySet(); //使用foreach遍历Set集合 for (Map.Entry<String,String> entry:entrySet ) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key+"的对象是"+value); /** * */ } } }
HashMap存储自定义类型键值
练习:
每位学生(姓名,年龄)都有自己的家庭住址。那么,既然有对应关系,则将学生对象和家庭住址存储到Map集合。学生作为键,家庭住址作为值。
package day04; public class Student { //成员变量 private String name; private int age; //无参构造方法 public Student() { } //全参构造方法 public Student(String name, int age) { this.name = name; this.age = age; } //get & set 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; } //重写toString @Override public String toString() { return "Student{" + "name='" + name + '\'' + ", age='" + age + '\'' + '}'; } }
package day04; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class practice { public static void main(String[] args) { //创建hashMap对象 键:学生 值:家庭住址 Map<Student,String> stuAddress = new HashMap<>(); //往集合添加对象 学生 以及 家庭住址 stuAddress.put((new Student("王俊凯",22)),"重庆"); stuAddress.put((new Student("易烊千玺",18)),"湖南"); stuAddress.put((new Student("王源",20)),"中国"); //通过Map的Entryset方法 获取Map对象中的所有键值对对象 Set<Map.Entry<Student, String>> Stu = stuAddress.entrySet(); //通过迭代器遍历 Iterator<Map.Entry<Student, String>> it = Stu.iterator(); while (it.hasNext()){ Map.Entry<Student,String> en = it.next(); Student s = en.getKey(); String add = en.getValue(); System.out.println(s.getAge()+"岁的"+s.getName()+",家住"+add); /** * 18岁的易烊千玺,家住湖南 * 22岁的王俊凯,家住重庆 * 20岁的王源,家住中国 */ } } }
//此处输出的对象是无序的
Map常用子类---LinkedHashMap
我们知道hashMap保证成对的元素唯一,且查询速度非常快(数组+链表/红黑树),但是存取元素是无序的,但是通过LinkedHashMap,我们就可以达到存取元素有序,且同样快速的效果
package day04; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; import java.util.Set; public class LinkedHashMap_demo { public static void main(String[] args) { //创建LinkedHashMap对象 LinkedHashMap<Integer,String > map = new LinkedHashMap<>(); //添加元素 map.put(1,"白展堂"); map.put(3,"吕秀才"); map.put(2,"佟湘玉"); map.put(4,"郭芙蓉"); System.out.println(map);//{1=白展堂, 3=吕秀才, 2=佟湘玉, 4=郭芙蓉} //顺序没有打乱 //通过entrySet 获取集合中所有键值对对象 Set<Map.Entry<Integer, String>> en = map.entrySet(); //迭代器遍历 Iterator<Map.Entry<Integer, String>> it = en.iterator(); while (it.hasNext()){ Map.Entry<Integer,String> p = it.next(); int num = p.getKey(); String name = p.getValue(); System.out.println(num+"===="+name); /** * 1====白展堂 * 3====吕秀才 * 2====佟湘玉 * 4====郭芙蓉 */ } } }
注意:
此处的有序,并不是指从小到大的排序,而是元素怎么存的 取出来的顺序就是什么样的
Map集合练习
需求:计算一个字符串中,每个字符出现的次数
分析:
1、获取一个字符串对象
2、创建Map集合,键代表字符,值代表次数
3、遍历字符串得到每个字符。
4、判断Map中是否有该键
5、如果没有,第一次出现,存储次数为1;如果有说明已经出现过,获取对应的值进行++,再次存储。
6、打印结果
package day04; import java.util.*; public class practice01 { public static void main(String[] args) { //获取用户输入的字符串 Scanner sc = new Scanner(System.in); System.out.print("请输入一个字符串:"); String str = sc.nextLine(); //调用方法 findChar(str); } //定义查找字符方法 public static void findChar(String line){ //创建Map集合存储 字符 次数 HashMap<Character,Integer> map = new HashMap<>(); //遍历字符串 for (int i = 0; i < line.length(); i++) { char c = line.charAt(i); //判断该字符是否存在map集合的键中 if(!map.containsKey(c)){//不包含这个键 map.put(c,1);//第一次添加 }else {//存在集合中 //获取之前的次数 Integer count =map.get(c); //再次存入map集合 map.put(c,++count); } } Set<Map.Entry<Character, Integer>> et = map.entrySet(); Iterator<Map.Entry<Character, Integer>> it = et.iterator(); while (it.hasNext()){ Map.Entry<Character,Integer> ET = it.next(); Character key = ET.getKey(); int value = ET.getValue(); System.out.println(key+" 出现了"+value+"次"); } } }
模拟斗地主洗牌发牌
规则:
1、一组54张扑克牌
2、54张牌顺序打乱
3、三个玩家参与游戏,三人交替摸牌,每人17张,剩余3张底牌
4、查看三人各自手中的牌(按照牌的大小顺序)、底牌
需求分析
1、准备牌:
完成数字与纸牌的映射关系:
使用双列集合Map(HashMap)集合,完成一个数字与字符串纸牌的对应关系
2、洗牌
Collections.shuffle()
3、发牌
将每人以及底牌设计为ArrayList,留三张底牌,剩余通过对3取模依次发牌,存放过程要求数字大小与斗地主规则大小对应
4、看牌
通过Map集合找到对应字符展示

package day04; import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.Set; public class pokerMap_pratice { public static void main(String[] args) { //创建Map集合 HashMap<Integer,String> pokerMap = new HashMap<>(); //创建花色 ArrayList<String> colors = new ArrayList<>(); ArrayList<String> numbers = new ArrayList<>(); //通过Collectios.addAll()存储花色 和数字 Collections.addAll(colors,"♥","♠","♣","♦"); Collections.addAll(numbers,"2","A","K","Q","J","10","9","8","7","6","5","4","3"); //设置编号?后期用于排序 int count = 1; pokerMap.put(count++,"大王"); pokerMap.put(count++,"小鬼"); //创建牌面 并存储到pokerMap中 for (String color:colors ) { for (String num : numbers ) { String card = color + num;//牌面 pokerMap.put(count++,card); } } //洗牌 //取出编号(Integer)集合 按照编号打乱 Set<Integer> numSet = pokerMap.keySet(); //因为要打乱顺序 所以先将编号转到List集合 防止默认排序 ArrayList<Integer> numList = new ArrayList<>(); numList.addAll(numSet); //打乱 Collections.shuffle(numList); //创建三个玩家 以及底牌 ArrayList<Integer> Nop1 = new ArrayList<>(); ArrayList<Integer> NOp2 = new ArrayList<>(); ArrayList<Integer> NOp3 = new ArrayList<>(); ArrayList<Integer> NOdp = new ArrayList<>(); //存储编号 for (int i = 0; i < numList.size(); i++) { //获取编号 int NO = numList.get(i); //留底牌 if(i>=51){ NOdp.add(NO); }else if(i%3==0){ Nop1.add(NO); }else if(i%3 == 1){ NOp2.add(NO); }else { NOp3.add(NO); } } //对编号进行排序 Collections.sort(Nop1); Collections.sort(NOp2); Collections.sort(NOp3); Collections.sort(NOdp); //进行牌面转换 ArrayList<String> player01 = new ArrayList<>(); ArrayList<String> player02 = new ArrayList<>(); ArrayList<String> player03 = new ArrayList<>(); ArrayList<String> dipai = new ArrayList<>(); for (Integer i: Nop1 ) { String card = pokerMap.get(i); player01.add(card); } for (Integer i:NOp2 ) { String card = pokerMap.get(i); player02.add(card); } for (Integer i:NOp3 ) { String card = pokerMap.get(i); player03.add(card); } for (Integer i: NOdp ) { String card = pokerMap.get(i); dipai.add(card); } //查看 System.out.println("雪影"+player01); System.out.println("萌王"+player02); System.out.println("雪精灵"+player03); System.out.println("底牌"+dipai); } }
主要是通过编号来排序的,例如大王是1 小王2....
--->先将编号存在一个数组中
--->将编号顺序打乱Collections.shuffle()
--->创建玩家集合
--->将打乱的编号存储到玩家集合中
--->将通过遍历玩家集合中的编号 通过get方式 转为牌面

浙公网安备 33010602011771号