600字范文,内容丰富有趣,生活中的好帮手!
600字范文 > 黑马毕向东Java课程笔记(day16-1-16-9):集合类(集合框架)——Map集合

黑马毕向东Java课程笔记(day16-1-16-9):集合类(集合框架)——Map集合

时间:2022-07-31 07:27:03

相关推荐

黑马毕向东Java课程笔记(day16-1-16-9):集合类(集合框架)——Map集合

1、Map集合

Map集合的基本特点如下:

接口 Map<K,V>:将键映射到值的对象。一个映射不能包含重复的键;每个键最多只能映射到一个值。(但是值可以重复) K - 此映射所维护的键的类型V - 映射值的类型

Map集合接口的常见方法与常见子类

Map集合:该集合存储键值对。一对一对往里存。而且要保证键的唯一性。1,添加。put(K key, V value) putAll(Map<? extends K,? extends V> m) 2,删除。clear() remove(Object key) 3,判断。containsValue(Object value) containsKey(Object key) isEmpty() 4,获取。get(Object key) size() values() entrySet() keySet() Map|--Hashtable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。jdk1.0.效率低。|--HashMap:底层是哈希表数据结构,允许使用 null 值和 null 键,该集合是不同步的。将hashtable替代,jdk1.2.效率高。|--TreeMap:底层是二叉树数据结构。线程不同步。可以用于给map集合中的键进行排序。Map集合的结构和Set很像,Set底层就是使用了Map集合。

2、Map的共性方法演示

Map方法的常见方法演示如下:

package pack;import java.util.*;class MapDemo {public static void main(String[] args) {//我们创建一个泛型为<String,String>的map对象,比如键是学号,键对应的值是学生Map<String,String> map = new HashMap<String,String>();//Map是接口,我们就创建其子类HashMap的对象//添加元素,put(K key, V value):返回值类型为VSystem.out.println(map.put("01", "zhangsan01"));//结果:nullSystem.out.println(map.put("01", "wangwu"));//结果:zhangsan01,并且01位置的值变为“wangwu”//说明:当你往一个键里面添加值的时候,新的值会替代老的值。这里返回的V代表的是put赋值之前原来这个键所对应的值!map.put("02", "zhangsan02");map.put("03", "zhangsan03");//特殊添加map.put(null, "haha");//将键设定为nullSystem.out.println("获取某个键的值:"+map.get(null));//发现可以获取null键的值“haha”,说明:HashMap集合null是可以作为键存在的map.put("04", null);//将值设定为null//发现可以获取04键的值“null”,但是这样是没有意义的,所以,若一个键的值为null,我们判断这个键不存在(get方法)!System.out.println("获取某个键的值:"+map.get("04"));//判断System.out.println("是否包含某个键:"+map.containsKey("02"));//是否包含某个键//删除//System.out.println("将某个键删除:"+map.remove("02"));//获取System.out.println("获取某个键的值:"+map.get("03"));//可以用get方法判断某个键是否存在:获取键对应的值,如果返回null说明键不存在//获取集合中所有的值。values():返回此映射中包含的值的 Collection 视图。Collection<String> coll = map.values();//既values返回一个Collection的集合,且集合元素类型为map值的类型。System.out.println(coll);//获取无序的结果:哈希数据结构是无序的//打印集合System.out.println(map);//{01=zhangsan01, 03=zhangsan03}:发现键“02”被删除,并且其对应的值也会被删除}}

Map的特殊方法——将Map集合的值全部取出:keySet与entrySet方法。前面我们使用values()方法可以将map集合的值全部存放到Collection集合的对象中,这样可以获取所有的值,但是没办法得到对应键的对应值;而get()方法可以得到对应键的对应值,但是没办法得到一批键的对应值,那么现在我们来介绍其他两种方法,可以获取一批键的对应值。

下面先介绍keySet:(16-4,6.30开始有keySet方法的画图演示)

1、keySet 返回值类型Set<k> :将map中所有的键存入到Set集合。因为Set具备迭代器,而Map集合不具备迭代器。我们可以获取Map集合所有键到Set集合中,再用迭代方式取出Set集合所有的键,再根据Map集合get方法。获取每一个键对应的值。Map集合的取出原理:将map集合转成set集合,再通过迭代器取出。

代码示例

package pack;import java.util.*;class MapDemo {public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("02", "zhangsan02");map.put("04", "zhangsan04");map.put("03", "zhangsan03");map.put("01", "zhangsan01");//首先,先获取Map集合键的Set集合Set<String> setObj = map.keySet();//再用迭代器将Set集合中的String对象,也就是Map集合的键取出Iterator<String> it = setObj.iterator();//先将Set的对象取到迭代器中while(it.hasNext()){String key = it.next();//将Set集合中的String对象一个一个取出,他们也是Map的键String value = map.get(key);//根据键将map的值也取出System.out.println("key:"+key+" value:"+value);}}}/*结果:(视频内没有自动排序,不知道为啥这里会自动排序,可能是JDK8的新特性)key:01 value:zhangsan01key:02 value:zhangsan02key:03 value:zhangsan03key:04 value:zhangsan04*/

下面再介绍entrySet:(16-5,6.20开始的图解释entrySet的原理)

2、Set<Map.Entry<k,v>> entrySet:将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry,既Map.Entry接口表示的就是Map中键与值的映射关系

代码示例

package pack;import java.util.*;class MapDemo {public static void main(String[] args) {Map<String,String> map = new HashMap<String,String>();map.put("02", "zhangsan02");map.put("04", "zhangsan04");map.put("03", "zhangsan03");map.put("01", "zhangsan01");//将Map集合中的映射关系取出到Set集合中,映射关系的数据类型是Map.Entry<K,V>Set<Map.Entry<String, String>> setObj = map.entrySet();//同样设置迭代器取出映射关系的对象Iterator<Map.Entry<String, String>> it = setObj.iterator();while(it.hasNext()){//将迭代器中的每一个映射关系对象(既Map.Entey<K,V>对象)取出,放到一个变量中Map.Entry<String, String> mapping = it.next();//返回实现Map.Entry<K,V>接口的子类的对象,类似迭代器原理//使用Map.Entry接口的方法获取映射关系中的键与值System.out.println("key:"+mapping.getKey()+" value:"+mapping.getValue());}}}/*结果:(自动排序,既HashMap元素排放的顺序与元素放入HashMap时的顺序不一致,因此可以看出HashMap是无序的)(注意有序指的是元素存储顺序与集合中元素排放的顺序一致)key:01 value:zhangsan01key:02 value:zhangsan02key:03 value:zhangsan03key:04 value:zhangsan04*/

关于Map.Entry<K,V>的解析

Entry其实就是Map中的一个static内部接口。为什么要定义在内部呢?因为只有有了Map集合,有了键值对,才会有键值的映射关系。既关系属于Map集合中的一个内部事物。而且该接口方法在直接访问Map集合中的元素。所以Entry接口定义在Map接口内部。

Enter接口的源代码

Map.Entry 其实Entry也是一个接口,它是Map接口中的一个内部接口。interface Map{public static interface Entry{public abstract Object getKey();public abstract Object getValue();}}class HashMap implements Map{class Hahs implements Map.Entry{public Object getKey(){}public Object getValue(){}}}

3、Map集合的练习

练习1——HashMap

/*描述:学生Student,一个学生对应一个地址String。学生属性:姓名,年龄,姓名和年龄相同的视为同一个学生,保证学生的唯一性。需求:1、描述学生;2、定义map容器,将学生作为键,地址作为值存入;(学生作为键不能重复,而地址作为值是可以重复的!)3、获取map集合中的元素。*/package pack;import java.util.*;class MapDemo {public static void main(String[] args) {//创建一个HashMap集合用于存储相应映射,键类型是Student,值类型是StringHashMap<Student,String> hm = new HashMap<Student,String>();hm.put(new Student("lisi1",21),"beijing");hm.put(new Student("lisi1",21),"tianjin");hm.put(new Student("lisi2",22),"shanghai");hm.put(new Student("lisi3",23),"nanjing");hm.put(new Student("lisi4",24),"wuhan");//第一种取出方法keySetSet<Student> setObj1 = hm.keySet();//先用keySet方法创建一个Set集合//构建迭代器取出键Iterator<Student> it = setObj1.iterator();//上面2句合并:Iterator<Student> it = hm.keySet().iterator();while(it.hasNext()){Student stu = it.next();//取出每一个Student对象String address = hm.get(stu);//通过HashMap的get(K)方法获取键值System.out.println("姓名:"+stu.getName()+" 年龄:"+stu.getAge()+" 地址"+address);}System.out.println();//第二种取出方法entrySetSet<Map.Entry<Student, String>> setObj2 = hm.entrySet();//用entrySet()方法创建包含Map.entry<K,V>对象的Set集合//同样创建相应迭代器并索引Iterator<Map.Entry<Student, String>> it1 = setObj2.iterator();while(it1.hasNext()){Map.Entry<Student, String> me = it1.next();//取出每一个Student对象Student stu = me.getKey();//获取键——Student对象String s = me.getValue();//获取值——String地址System.out.println("姓名:"+stu.getName()+" 年龄:"+stu.getAge()+" 地址"+s);}}}//创建一个学生类继承Comparable接口,实现学生类的比较性(为了防止使用二叉树存储时无法比较,当然使用List存储的时候也可以进行比较,因为List和TreeSet一样有顺序,可以比较元素)//且该Comparable指定的比较类型应该是Student,因为最终参与比较的应该是Student的不同对象class Student implements Comparable<Student>{private String name;private int age;Student(String name,int age){this.name = name;this.age = age;}//提供获取name与age的方法public String getName(){return name;}public int getAge(){return age;}//重写Comparable的compareTo方法以实现比较,Comparable已经限定比较对象为Student,因此compareTo的对象只需要设定Student即可@Overridepublic int compareTo(Student s) {//先比较年龄,年龄相同再比较姓名,这种比较的先后顺序没什么区别int num = new Integer(this.age).compareTo(new Integer(s.age));//Integer与String都有compareTo方法//num=0,年龄相同,再比较姓名if(num == 0)return pareTo(s.name);return num;}//涉及Hash的我们都重写hashCode与equals方法,比较需要用到!//重写hashCode方法,使得姓名与年龄不同的Student对象哈希值不同public int hashCode(){return name.hashCode()+age*23;}//重写equals方法,比较姓名与年龄。注意equals继承自Object,因此其参数必须为Objectpublic boolean equals(Object obj){//因为参数为Object,因此必须先判断obj是否属于Objectif(!(obj instanceof Student))throw new ClassCastException("比较的对象不属于Student类,出错!");//抛出RuntimeException的子类ClassCastException更加准确Student s = (Student)obj;//将obj对象向下转型为Student类型//如果姓名年龄相同则返回truereturn this.name.equals(s.name) && this.age == s.age;//String的equals用于比较内容}//重写toString方法public String toString(){return name+":"+age;}}/*结果:不设置重复元素:结果是无序的,对应哈希表数据结构是无序的姓名:lisi1 年龄:21 地址beijing姓名:lisi3 年龄:23 地址nanjing姓名:lisi2 年龄:22 地址shanghai姓名:lisi4 年龄:24 地址wuhan结果2:设置重复元素:没有出现重复的元素,并且lisi1出现在tianjin我们做了hashCode()与equals()方法的复写,HashMap调用这2个方法判断前2个Student对象相同。(注意HashMap比较键也是用hashCode与equals)Map中键不能相同,因为Student对象相同,因此后面传入的相同的Student对象就会覆盖前面的键,它指向的是tianjin的值姓名:lisi1 年龄:21 地址tianjin姓名:lisi3 年龄:23 地址nanjing姓名:lisi2 年龄:22 地址shanghai姓名:lisi4 年龄:24 地址wuhan*/

TreeMap不会对存放的对象进行排序,但是可以通过compareTo方法比较对象是否相同。而下面的TreeMap会使用compareTo方法比较对象是否相同,并通过对象大小对对象进行排序。

练习2:TreeMap

/*需求:我们前面实现Comparable的自然顺序是依照学生的年龄排序,对比年龄相同后再比较姓名。我们现在想根据学生的姓名排序——先比较姓名,姓名相同再比较年龄。——利用比较器因为数据是以键值对形式存在的,所以要使用可以排序的Map集合——TreeMap。——TreeMap会排序——Comparable或者Comparator*/package pack;import java.util.*;class MapDemo {public static void main(String[] args) {//创建一个HashMap集合用于存储相应映射,键类型是Student,值类型是StringTreeMap<Student,String> tm = new TreeMap<Student,String>(new StuNameCompare());tm.put(new Student("blisi3",23),"nanjing");tm.put(new Student("lisi1",21),"beijing");tm.put(new Student("alisi4",24),"wuhan");tm.put(new Student("lisi1",21),"tianjin");tm.put(new Student("lisi2",22),"shanghai");Set<Map.Entry<Student, String>> setObj = tm.entrySet();Iterator<Map.Entry<Student, String>> it = setObj.iterator();while(it.hasNext()){Map.Entry<Student, String> me = it.next();//取出每一个Student对象Student stu = me.getKey();//获取键——Student对象String s = me.getValue();//获取值——String地址System.out.println("姓名:"+stu.getName()+" 年龄:"+stu.getAge()+" 地址"+s);}}}//创建一个比较器的类class StuNameCompare implements Comparator<Student>{public int compare(Student s1,Student s2){//先比较姓名int num = s1.getName().compareTo(s2.getName());if(num == 0)//姓名相同再比较年龄,都一样就是同一个对象,同一个键!return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge()));return num;}}class Student implements Comparable<Student>{private String name;private int age;Student(String name,int age){this.name = name;this.age = age;}public String getName(){return name;}public int getAge(){return age;}public int compareTo(Student s) {int num = new Integer(this.age).compareTo(new Integer(s.age));if(num == 0)return pareTo(s.name);return num;}public int hashCode(){return name.hashCode()+age*23;}public boolean equals(Object obj){if(!(obj instanceof Student))throw new ClassCastException("比较的对象不属于Student类,出错!");Student s = (Student)obj;return this.name.equals(s.name) && this.age == s.age;}public String toString(){return name+":"+age;}}/*结果1:发现元素自动排序——因为学生Student实现了Comparable接口,具备自然顺序(Comparable的自然顺序是按照年龄排序)姓名:lisi1 年龄:21 地址beijing姓名:lisi2 年龄:22 地址shanghai姓名:lisi3 年龄:23 地址nanjing姓名:lisi4 年龄:24 地址wuhan结果2:修改Student元素,并添加重复的Student元素(添加比较器Comparator)姓名:alisi4 年龄:24 地址wuhan姓名:blisi3 年龄:23 地址nanjing姓名:lisi1 年龄:21 地址tianjin姓名:lisi2 年龄:22 地址shanghai发现先按姓名自动排序,而且相同的Student作为TreeMap的键会被后面进来的相同Student对象覆盖!*/

练习3:TreeMap练习2

/*练习:"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2).....分析:通过结果发现,每一个字母都有对应的次数,说明字母和次数之间都有映射关系。注意了,当发现有映射关系时,可以选择map集合,因为map集合中存放就是映射关系。以后当数据之间存在这映射关系时,就要先想map集合。思路:1、将字符串转换成字符数组,因为要对每一个字母进行操作。2、定义一个map集合,因为打印结果的字母有顺序,所以使用treemap集合。该集合的键为字母(Character)、集合的值为字母出现的次数3、遍历字符数组。将每一个字母作为键去查map集合。如果返回null,说明该字母在之前没有存入,将该字母和1存入到map集合中。如果返回不是null,说明该字母在map集合已经存在并有对应次数。那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到map集合中,覆盖调用原理键所对应的值。4、将map集合中的数据变成指定的字符串形式返回。*/package pack;import java.util.*;class MapDemo {public static void main(String[] args) {String s = charCount("ak+abAf1c,dCkaAbc-defa");System.out.println(s);}//创建一个方法来实现字母计数的功能:返回值为要求的字符串,输入值参数为需要计数的字符串public static String charCount(String str){//首先将需要计数的字符串放入字符数组中char[] charArr = str.toCharArray();//其次创建一个TreeMap集合用于存储字母以及其出现的顺序TreeMap<Character,Integer> tm = new TreeMap<Character,Integer>();//集合中存放的必须是对象,因此使用Integer表示整形,这样才能将对象存放进去。Integer timeValue = 0;//定义一个变量用于存储字母次数//第二种插入方法int count = 0;//定义一个临时的计数器并初始化为0//下面根据字符数组的长度遍历该字符数组for(int x=0; x<charArr.length ; x++){//首先,如果要排序的字符串数组中的字符不是字母,那么这次循环就跳过,继续下一次循环,这种字符不需要存入if(!((charArr[x]>='a' && charArr[x]<='z')||(charArr[x]>='A' && charArr[x]<='Z')))continue;//跳过此处循环,进入下一次循环//如果查询的是字母,我们检查该字母在tm中存储的出现的次数timeValue = tm.get(charArr[x]);//我们用另一种方法来将字母与其出现次数插入集合if(!(timeValue == null))//若字母在集合中存储的次数不为null,将timeValue的值赋予临时计数器count;count = timeValue;//这里Integer类型拆箱为int类型count++;//不管timeValue之前是否为0,次数都会自加1。如果不设置count,在timeValue == null的时候,次数表示为null,而不是0次,这与我们的需求是不符的。因为null是无法进行自加操作的。tm.put(charArr[x], count);count = 0;//当然最后还是要将count置零,保证下一次进来的字母保存初始次数为0./*if(timeValue == null)//这里注意timeValue只能为null,而不是为0,因为其是从集合中取出的,集合中元素不存在定义为null{tm.put(charArr[x], 1);//将该字母及其出现次数1存入tm}else{tm.put(charArr[x],timeValue+1);//将该字母及其出现value+1存入tm}*/}//循环将字母与次数存储到tm完毕后,我们遍历将其取出,并通过StringBuilder的append方法将各个字母及存入字符串中StringBuilder sb = new StringBuilder();//先创建Map.Entry<Character, Integer>类型的Set集合Set<Map.Entry<Character, Integer>> entrySet = tm.entrySet();//再创建迭代器Iterator<Map.Entry<Character, Integer>> it = entrySet.iterator();while(it.hasNext()){Map.Entry<Character, Integer> me = it.next();//先将Map.Entry<Character, Integer>对象取出//再获取键与值Character charKey = me.getKey();Integer intValue = me.getValue();//接下来将字符(键)与次数(值)添加到sbsb.append(charKey+"("+intValue+")");}//最后返回sb.toString既是我们想要的字符串(StringBuilder对象提供toString将对象转换为字符串)return sb.toString();}}/*结果:A(2)C(1)a(4)b(2)c(2)d(2)e(1)f(2)k(2)由于Character实现了Comparable,因此TreeSet中字母具有默认的自然排序!*/

4、Map集合扩展

先看如下示例

/*map扩展知识,map集合被使用是因为具备映射关系。试着存储如下内容:有2个映射关系:"yureban" Student("01" "zhangsan");"yureban" Student("02" "lisi");"jiuyeban" "01" "wangwu";"jiuyeban" "02" "zhaoliu";分析:班级对应学生,而学生中学号对应姓名。有多个班级,一个班级可能对应很多学生,这是一对多映射;一个学号值对应一个姓名,这是我们之前将的一对一映射。现在要选择处理一对多映射的方法*/package pack;import java.util.*;class MapDemo {public static void main(String[] args) {//首先创建一个HashMap集合,对预热班的学生进行描述,这里描述的是预热班中学生学号(String)与姓名(String)的一对一关系HashMap<String,String> yure = new HashMap<String,String>();//往预热班中添加学生yure.put("01", "zhangsan");yure.put("02", "lisi");//同样创建就业班的集合HashMap<String,String> jiuye = new HashMap<String,String>();jiuye.put("01", "wangwu");jiuye.put("02", "zhaoliu");//接下来,我们对班级与学生之间进行描述,由于有多个班级,且一个班级对应多个学生//那么我们创建班级名称(String)与存储多个学生实体的班级集合的HashMap集合(16-9,7.30处解析)HashMap<String,HashMap<String,String>> czbk = new HashMap<String,HashMap<String,String>>();//添加班级名称与班级集合czbk.put("yure", yure);czbk.put("jiuye", jiuye);//接下来,我们创建Set集合与迭代器遍历czdb集合Set<String> keySet = czbk.keySet();Iterator<String> it = keySet.iterator();while(it.hasNext()){//获取String类型的键,既班级名称String className = it.next();//通过键获取值,既班级HashMap<String,String> classValue = czbk.get(className);System.out.println("班级名称为:"+className);//再通过getStudentInfo()方法遍历班级集合中的元素MapDemo.getStudentInfo(classValue);}}//创建遍历班级集合的方法public static void getStudentInfo(HashMap<String,String> map){Set<Map.Entry<String, String>> entrySet = map.entrySet();Iterator<Map.Entry<String, String>> it = entrySet.iterator();while(it.hasNext()){//获取Map.Entry<String, String>类型的对象Map.Entry<String, String> me = it.next();String id = me.getKey();String name = me.getValue();System.out.println("学号:"+id+" 姓名"+name);}}}/*结果:成功遍历!班级名称为:jiuye学号:01 姓名wangwu学号:02 姓名zhaoliu班级名称为:yure学号:01 姓名zhangsan学号:02 姓名lisi*/

我们将上面的例子进行优化

/*我们将学生封装成为Student类来描述,由于学号有顺序,且每一个学生Student都不能重复,这样将其设置为HashMap类型,这样作为HashMap的值(可重复)不合适,那么我们用List来存储Student对象(16-9.19.30开始解析)"yureban" Student("01" "zhangsan");"yureban" Student("02" "lisi");"jiuyeban" "01" "wangwu";"jiuyeban" "02" "zhaoliu";*/package pack;import java.util.*;class MapDemo {public static void main(String[] args) {MapDemo.printInfo();//打印所有信息}//创建一个遍历打印所有班级与学生信息的方法public static void printInfo(){//同样先创建学校HashMap集合HashMap<String,List<Student>> czbk = new HashMap<String,List<Student>>();//创建班级List集合,其为Student类型List<Student> yure = new ArrayList<Student>();List<Student> jiuye = new ArrayList<Student>();//添加班级czbk.put("yure", yure);czbk.put("jiuye", jiuye);//为各个班级添加学生yure.add(new Student("01","zhangsan"));yure.add(new Student("02","lisi"));jiuye.add(new Student("01","wangwu"));jiuye.add(new Student("02","zhaoliu"));MapDemo.getClassInfo(czbk);//遍历班级名与各个班级实体}//我们创建获取学校HashMap集合班级信息的方法public static void getClassInfo(HashMap<String,List<Student>> sch){Iterator<String> it = sch.keySet().iterator();while(it.hasNext()){//获取键,既班级名称String className = it.next();//获取班级实体,为List<Student>类型List<Student> classValue = sch.get(className);System.out.println("班级:"+className);MapDemo.getStudentInfo(classValue);//遍历班级内的学生学号与姓名}}//我们再创建获取班级List集合中学号与姓名信息的方法public static void getStudentInfo(List<Student> classValue){Iterator<Student> it = classValue.iterator();while(it.hasNext()){//获取学生对象Student stu = it.next();//打印学生信息System.out.println("学号:"+stu.getId()+" 姓名"+stu.getName());}}}//Student类class Student{private String id;private String name;Student(String id,String name){this.id = id;this.name = name;}public String getId(){return id;}public String getName(){return name;}}/*结果:成功遍历!班级:jiuye学号:01 姓名wangwu学号:02 姓名zhaoliu班级:yure学号:01 姓名zhangsan学号:02 姓名lisi*/

4、Map集合补充

补充1

HashMap集合的特点

HashMap集合的特点:1.HashMap集合底层是哈希表:查询的速度特别的快JDK1.8之前:数组+单向链表JDK1.8之后:数组+单向链表|红黑树(链表的长度超过8):提高查询的速度2.hashMap集合是一个无序的集合,存储元素和取出元素的顺序有可能不一致java.util.LinkedHashMap<k,v>集合 extends HashMap<k,v>集合LinkedHashMap的特点:1.LinkedHashMap集合底层是哈希表+链表(保证迭代的顺序)2.LinkedHashMap集合是一个有序的集合,存储元素和取出元素的顺序是一致的

补充2

Map.Entry接口的解析(见就业班Map接口-05)

补充3

HashMap存储自定义类型键值(见就业班Map接口-07)

Map集合保证key是唯一的:作为key的元素,必须重写hashCode方法和equals方法,以保证key唯一。底层在添加的时候会调用这两个方法,判断要添加的key值对象是否与之前添加过的对象相同,不同则存储,反之不存储。Hash结构的集合调用equals与hashCode方法,以比较存储的对象是否相同。

补充4

有序版本的斗地主

package lkj.demo1;import java.util.ArrayList;import java.util.Collections;import java.util.HashMap;import java.util.List;public class DouDiZhu{/*斗地主综合案例:有序版本1.准备牌2.洗牌3.发牌4.排序5.看牌*/public static void main(String[] args){//1.准备牌//创建一个Map集合,存储牌的索引和组装好的牌HashMap<Integer,String> poker = new HashMap<>();//创建一个List集合,存储牌的索引ArrayList<Integer> pokerIndex = new ArrayList<>();//定义两个集合,存储花色和牌的序号List<String> colors = new ArrayList<>();List<String> numbers = new ArrayList<>();//使用Collections的addAll方法往ArrayList集合中添加元素.//这里没办法使用JDK9的of方法。只能使用Collections方法addAll方法替代Collections.addAll(colors,"♠", "♥", "♣", "♦");Collections.addAll(numbers,"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 col:colors){for(String num:numbers){poker.put(index,col+num);pokerIndex.add(index);index++;}}// System.out.println(poker);/*2.洗牌使用Collections中的方法shuffle(List)*/Collections.shuffle(pokerIndex);//将索引集合的顺序打乱/*3.发牌*///定义4个集合,存储玩家牌的索引,和底牌的索引ArrayList<Integer> player01 = new ArrayList<>();ArrayList<Integer> player02 = new ArrayList<>();ArrayList<Integer> player03 = new ArrayList<>();ArrayList<Integer> diPai = new ArrayList<>();//遍历存储牌索引的List集合,获取每一个牌的索引for (int i = 0; i < pokerIndex.size(); i++){Integer in = pokerIndex.get(i);//获取索引集合pokerIndex的值,并将其赋予每一个玩家的集合if(i>=51){diPai.add(in);}if(i%3 == 0){player01.add(in);}else if(i%3 == 1){player02.add(in);}else if(i%3 == 2){player03.add(in);}}/*4.排序使用Collections中的方法sort(List)默认是升序排序*/Collections.sort(player01);Collections.sort(player02);Collections.sort(player03);Collections.sort(diPai);/*5.看牌调用看牌的方法*/lookPoker("刘德华",poker,player01);lookPoker("周润发",poker,player02);lookPoker("周星驰",poker,player03);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+":");//遍历玩家或者底牌集合,获取牌的索引——需要注意的是,这里必须通过list的Integer元素来查找poker中的元素for (int i=0 ; i<list.size() ;i++){//使用牌的索引,去Map集合中,找到对应的牌String value = poker.get(list.get(i));System.out.print(value+" ");}System.out.println();//打印完每一个玩家的牌,换行}}

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。