【Java的集合框架 Map 29】
总结Collection集合知识点:
后缀名就是该集合所属的体系
前缀名就是该集合的数据结构
看到array:就要想到数组,就要想到查询快,有角标
看到link:就要想到链表,就要想到增删快,就要想到add get remove+first last的方法
看到hash:就要想到哈希表,就要想到唯一性,就要想到元素需要覆盖hashcode方法和equals方法
看到tree:就要想到二叉树,就要想到排序,就要想到两个接口comparaable,comparator
而且通常这些常用的集合容器都是不同步的
其实以上集合,核心的几点都是各自的方法,子类以及对应获取集合内的元素
list集合是有序,可重复;
set集合是无序,不可重复;
ArrayList,LinkedList 取不重复的元素,需要定义一个中间的集合,用contain来判断
HashSet,TreeSet 本身的集合就是不可重复的。
四个集合存基本数据类型的数据,迭代去元素时直接调用迭代Iterator接口即可
如果存的是引用类型的对象,迭代元素时都需要引用类重写hashcode(),equals(),toString()方法,
其中HashSet需要先判断元素的哈希值是否相同,然后在判断内容是否相同
TreeSet有两种方式进行比较重复判断的方式:1、让对象本身具备具备比较功能(comparable)
2、让几个具备比较功能(comparator)
==============================================
一、集合特点
Map<K,V>
类型参数:
K - 此映射所维护的键的类型
V - 映射值的类型
Map:一次添加一对元素。collection一次添加一个元素
Map也称双列集合,Collection集合称为单列集合。其实map集合中存储的就是键值对,map集合必须保证键的唯一性。
二、常用方法:
1、添加
value put(key value):返回前一个和key关联的值,如果没有返回null
2、删除
void clear():清空map集合
value remove(key):根据指定的key翻出这个键值对
3、判断
boolean containsKey(key):
boolean containsValue(value)
boolean isEmpty()
4、获取
value get(key):通过键获取值,如果没有该键返回null。
当然可以通过返回null,来判断是否包含指定键
int size():获取键值对的个数。
-------> 代码演示方法<--------
package com.JavaStudy01.Map; import java.util.HashMap; import java.util.Map; /** * @Author wufq * @Date 2020/8/7 10:01 */ public class MapDemo01 { public static void main(String[] args){ Map<Integer,String> map = new HashMap<Integer, String>(); method(map); } private static void method(Map<Integer, String> map) { //增加 System.out.println(map.put(2,"wangcai"));//null -->相同键值,value值会被覆盖 System.out.println(map.put(2,"xiaoqiang"));//wangcai -->返回前一个和key关联的值 map.put(7,"zhangsan"); map.put(5,"lisi") ; System.out.println("添加后完整的map:"+map); //删除 map.remove(5); //判断 System.out.println(map.containsKey(5));//true //获取 System.out.println(map.get(5));//lisi System.out.println(map);//{2=xiaoqiang} -->key和value进行了关联 } }
5、重点:获取map中所有的元素
Map集合里面是没有迭代器的,那么要想获取集合里面的元素,思路是把map集合转换成Set集合
转换的两张方法:
第一种:使用keySet()方法 --> 获取map集合内所有的键存放到Set集合内,然后通过键取每一个值即可
第二种:使用entrySet()方法 --> 该方法将键和值作为映射对象存储到Set集合内,(entrySet()的映射对象是Map.entry<K,V>)然后通过Map.entry的getKey()和getValue
方法获取键和值
Map.Entry<K,V>是Map<K,V>的嵌套类
public static interface Map.Entry<K,V>
Map.EntrySet方法返回映射的Collection视图,其中的元素属于此类。获得映射项引用的唯一的方法是通过此collection视图的迭代器来实现。
方法:
boolean equals(Object o) ;比较指定对象与此项的相等性
K getKey();返回此项的键
V getValue():返回此项的值
V setValue():用指定的值替换此项对应的值
package com.JavaStudy01.Map; import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; /** * @Author wufq * @Date 2020/8/7 10:01 * 获取集合内所有元素,思路是:通过map转换成set就可以迭代 */ public class MapDemo01 { public static void main(String[] args){ Map<Integer,String> map = new HashMap<Integer, String>(); method_2(map); method_3(map); } /* 第一种方法:keySet 原理:通过keySet方法获取map中所有键所在的set集合,然后通过set集合的迭代器获取每一个键,在对每一个键取其对应的值即可 */ public static void method_2(Map<Integer, String> map) { map.put(7,"zhangsan"); map.put(5,"lisi") ; map.put(8,"wangcai"); map.put(1,"xiaoqiang") ; map.put(2,"wangwu"); map.put(3,"zhaoliu") ; Set<Integer> keySet = map.keySet(); Iterator<Integer> it=keySet.iterator(); while (it.hasNext()){ Integer key = it.next(); String value = map.get(key); System.out.println(key+"::"+value); } } /* 第二种方法:entrySet() Map集合内的方法 原理:该方法将键和值的映射关系作为对象存储到set集合中,而这个映射关系就是Map.Entry类型(结婚照) */ public static void method_3(Map<Integer, String> map) { map.put(7,"zhangsan"); map.put(5,"lisi") ; map.put(8,"wangcai"); map.put(1,"xiaoqiang") ; map.put(2,"wangwu"); map.put(3,"zhaoliu") ; Set<Map.Entry<Integer,String>> entrySet = map.entrySet(); Iterator<Map.Entry<Integer,String>> it = entrySet.iterator(); while (it.hasNext()){ Map.Entry<Integer,String> me= it.next(); Integer key = me.getKey(); String value = me.getValue(); System.out.println(key+"::"+value); } } }
第一种方法原理图:
第二中方法原理图:
三、Map常用子类
|-- Hashtable:内部结构是哈希表,是同步的。不允许null作为键,null作为值
|-- properties:用来存储键值对型的配置文件的信息,可以和IO技术相结合
|-- HashMap:内部结构是哈希表,是不同步的
|-- TreeMap:内部结构是二叉树,不是同步的,可以对Map集合中的键进行排序
1、HashMap存储自定义对象
需求:将学生对象和学生的归属地通过键与值存储到map集合中
---------->Students类<-----------
package com.JavaStudy01.Bean; /** * @Author wufq * @Date 2020/8/7 16:43 */ public class Students { private String name; private int age; public Students(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 int hashCode() { return name.hashCode()+age; } @Override public boolean equals(Object obj) { Students stu = (Students)obj; return this.name.equals(stu.name)&&this.age==stu.age; } }
---------->HashMapDemo01类<-----------
package com.JavaStudy01.Map; import com.JavaStudy01.Bean.Students; import java.util.HashMap; import java.util.Iterator; /** * @Author wufq * @Date 2020/8/7 16:29 * 将学生对象和学生的归属地通过键与值存储到map集合中 */ public class HashMapDemo01 { public static void main(String[] args){ HashMap<Students,String> hm = new HashMap<Students,String>(); hm.put(new Students("张三",22),"北京"); hm.put(new Students("李四",23),"上海"); hm.put(new Students("王五",29),"广州"); hm.put(new Students("赵六",28),"深圳"); hm.put(new Students("李四",23),"铁岭"); // Set<Students> st = hm.keySet(); // Iterator<Students> iter = st.iterator(); //上面的写法可以直接写成这样 Iterator<Students> iter = hm.keySet().iterator(); while (iter.hasNext()){ Students key = iter.next(); String value = hm.get(key); System.out.println(key.getName()+":"+key.getAge()+"---"+value); } } }
执行结果:
张三:22---北京
李四:23---铁岭
赵六:28---深圳
王五:29---广州
李四:23---上海
从上面的执行结果可以看出:李四的城市铁岭没有覆盖上海,所以这里面又涉及到一个知识点,hashMap的数据结构也是哈希表,所以需要重写hashCode和equals方法
重写以后执行结果:
张三:22---北京
赵六:28---深圳
李四:23---铁岭
王五:29---广州
2、TreeMap存储自定义对象
---------->ComparatorByName类继承Comparator接口,重写compare方法<----------------
package com.JavaStudy01.Bean; import java.util.Comparator; /** * @Author wufq * @Date 2020/8/6 14:37 */ public class ComparatorByName implements Comparator<Students>{ @Override public int compare(Students p1, Students p2) { int temp = p1.getName().compareTo(p2.getName()); return temp==0?p1.getAge()-p2.getAge():temp; } }
---------->TreeMapDemo01类<----------------
package com.JavaStudy01.Map; import com.JavaStudy01.Bean.ComparatorByName; import com.JavaStudy01.Bean.Students; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; /** * @Author wufq * @Date 2020/8/8 11:21 */ public class TreeMapDemo01 { public static void main(String[] args){ TreeMap<Students,String> tm = new TreeMap<>(new ComparatorByName()); tm.put(new Students("张三",22),"北京"); tm.put(new Students("李四",23),"上海"); tm.put(new Students("王五",29),"广州"); tm.put(new Students("赵六",28),"深圳"); tm.put(new Students("李四",23),"铁岭"); Iterator<Map.Entry<Students,String>> iter=tm.entrySet().iterator(); while(iter.hasNext()){ Map.Entry<Students,String> me=iter.next(); Students stu = me.getKey(); String value = me.getValue(); System.out.println(stu.getName()+":"+stu.getAge()+value); } } }
=====执行结果======
张三:22北京
李四:23铁岭
王五:29广州
赵六:28深圳
3、linkedHashMap 有序排列(有序指的是集合内怎么存就怎么取)
package com.JavaStudy01.Map; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedHashMap; import java.util.Map; /** * @Author wufq * @Date 2020/8/8 15:11 * LinkedHashMap有序排列(指的是怎么存怎么取) */ public class LinkedHashMapDemo01 { public static void main(String[] args){ HashMap<Integer,String> hm = new LinkedHashMap<>(); hm.put(2,"aaa"); hm.put(7,"aba"); hm.put(5,"aca"); hm.put(1,"ada"); Iterator<Map.Entry<Integer,String>> it = hm.entrySet().iterator(); while (it.hasNext()){ Map.Entry<Integer,String> me = it.next(); Integer key = me .getKey(); String value = me.getValue(); System.out.println(key+"::::"+value); } } } =====执行结果===== 2::::aaa 7::::aba 5::::aca 1::::ada
四、练习
练习一:"fghjvbfghfgh"获取该字符串中,每一个字母出现的次数,要求打印结果是;a(2)b(1)...;
package com.JavaStudy01.Map; import java.util.Iterator; import java.util.Map; import java.util.TreeMap; /** * @Author wufq * @Date 2020/8/8 15:27 * 练习; "fghjvbfghfgh"获取该字符串中,每一个字母出现的次数,要求打印结果是;a(2)b(1)...; 思路: 分析结果字母和次数是存在映射关系的,而且这种关系是很多的并且是需要存储的,那么存储映射关系的有数组和map集合, 这种映射关系是没有编号的,并且按照abc...这样进行排序的,所以使用TreeMap(TreeMap的特点是可以对键进行排序) 步骤: 1、把字符串转换成字符数组 2、创建一个TreeMap集合存储字母和次数 3、遍历数组,用每一个字母作为键去查Map集合的这个表 |-- 如果键不存在,则值=1 |-- 如果键存在,则值+1 4、重新组装map集合,已使返回的结果形式为a(2)b(1)... */ public class MapTest01 { public static void main(String[] args){ String str = "AAfghj vdf!@g$hfghKK"; String s = strToArray(str); System.out.println(s); } //字符串通过字符数组、集合转换成字符串 public static String strToArray(String str) { //将字符串变成字符数组 char[] chars = str.toCharArray(); //定义一个集合 Map<Character,Integer> map = new TreeMap<>(); //遍历数组内的元素 for(int i=0;i<chars.length;i++){ //字符串内有空格和特殊符号,需要跳过后继续统计 if(!(chars[i]>='a'&&chars[i]<='z'||chars[i]>='A'&&chars[i]<='Z')) { continue; } //通过数组的index去获取集合内的值 Integer value = map.get(chars[i]); /* /判断是否为空的第一种写法<-------- int count=0; if(value!=null){ count=value; } count++; map.put(chars[i],count); */ /* /判断是否为空的第二种写法<-------- */ int count = 1; if(value!=null){ count = value+1; } map.put(chars[i],count); /* /判断值是否为空第三种写法<--------- if(value==null){ map.put(chars[i],1); }else { map.put(chars[i],value+1); } */ } return mapToString(map); } //把集合内的对象转换成这样的格式:a(2)b(1)... private static String mapToString(Map<Character, Integer> map) { Iterator<Map.Entry<Character,Integer>> iter = map.entrySet().iterator(); StringBuilder sb = new StringBuilder(); while (iter.hasNext()){ Map.Entry<Character,Integer> me =iter.next(); Character key = me.getKey(); Integer value = me.getValue(); sb.append(key+"("+value+")"); } return sb.toString(); } } ====执行结果==== A(2)K(2)d(1)f(3)g(3)h(3)j(1)v(1)
练习二:
package com.JavaStudy01.Map; import java.util.HashMap; import java.util.Map; /** * @Author wufq * @Date 2020/8/8 18:38 * Map在有映射时,优先使用 * * 在查表法中优先使用 */ public class MapTest02 { public static void main(String[] args){ String weeks = getWeek(3); System.out.println(weeks); String weeks1=getMapWeeks(weeks); System.out.println(weeks1); } //通过map集合里面的key(即:礼拜一...)去查value(Mon...) public static String getMapWeeks(String week) { Map<String,String> map = new HashMap<>(); map.put("礼拜一","Mon"); map.put("礼拜二","Tus"); map.put("礼拜三","Wen"); map.put("礼拜四","Fou"); map.put("礼拜五","Fir"); map.put("礼拜六","Str"); map.put("礼拜日","Sun"); return map.get(week); } //通过输入数字,查找礼拜一,二... public static String getWeek(int week) { if(week<1 || week>7){ throw new RuntimeException("输入错误,请重新输入"); } String[] weeks = {"","礼拜一","礼拜二","礼拜三","礼拜四","礼拜五","礼拜六","礼拜日"}; return weeks[week]; } } ====执行结果==== 礼拜三 Wen