Java集合框架(三)
Map
Map集合:该集合存储键值对,一对一对的往里存,而且要保证键的唯一性。
Map
|------HashTable:底层是哈希表数据结构,不可以存入null键null值。该集合是线程同步的。JDK1.0,效率低。
|------HashMap:底层是哈希表数据结构,允许使用 null值和 null键,该集合是不同步的。JDK1.2,效率高。
|------TreeMap:底层是二叉树数据结构,线程不同步,可以给map集合中的键进行排序。
和Set很像,其实,Set底层就是使用了Map集合。
方法总结:
1、添加
put(K key, V value)
putAll(Map<? extends K,? extends V> m)
2、删除
clear()
remove(Object key)
3、判断
containsKey(Object key)
containsValue(Object value)
isEmpty()
4、获取
get(Object key)
size()
values()
entrySet()
keySet()
示例代码如下:
import java.util.Collection; import java.util.HashMap; import java.util.Map; public class MapDemo { public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); //添加元素 //添加元素,如果出现添加时,相同的键,那么后添加的值会覆盖原有的键对应的值,并put()方法返回被覆盖的值。 System.out.println("put:" + map.put("01", "zhangsan01"));//输出null System.out.println("put:" + map.put("01", "wangwu")); map.put("02", "zhangsan02"); map.put("03", "zhangsan03"); //System.out.println("containsKey:" + map.containsKey("022")); //System.out.println("remove:" + map.remove("02")) ; //可以通过get()方法的返回值来判断一个键是否存在,通过返回null来判断 System.out.println("get:" + map.get("023")); map.put(null, "haha");//HashMap允许使用 null值和 null键 map.put("04", null); System.out.println("get:" + map.get("04")); System.out.println("get:" + map.get(null)); //获取集合中所有的值 Collection<String> coll = map.values(); System.out.println(coll); System.out.println(map); } }
Map集合的两种取出方式
Map集合的两种取出方式:
1、Set<K> keySet():将map所有的键存入到Set集合,因为Set集合具备迭代器,所以可以迭代方式取出所有的键,在根据get()方法,获取每一个键对应的值。
Map集合的取出原理:将map集合转成set集合,在通过迭代器取出。
2、Set<Map.Entry<K,V>> entrySet():将map集合中的映射关系存入到了set集合中,而这个关系的数据类型就是:Map.Entry。
Map.Entry,其实Entry也是一个接口,它是Map接口中的一个内部接口。代码如下:
interface Map { public static interface Entry { public abstract Object getKey(); public abstract Object getValue(); } } class HashMap implements Map { class Haha implements Map.Entry { public Object getKey() { } public Object getValue() { } } }
示例代码:
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; public class MapDemo1 { public static void main(String[] args) { Map<String, String> map = new HashMap<String, String>(); map.put("01", "zhangsan01"); map.put("02", "zhangsan02"); map.put("03", "zhangsan03"); map.put("04", "zhangsan04"); //将map集合中的映射关系取出,存入到set集合中 Set<Map.Entry<String, String>> entrySet = map.entrySet(); Iterator<Map.Entry<String, String>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<String, String> me = it.next(); String key = me.getKey(); String value = me.getValue(); System.out.println(key + ":" + value); } /* //先获取map集合的所有的键的Set集合,keySet() Set<String> keySet = map.keySet(); //有了Set集合,就可以获取其迭代器 Iterator<String> it = keySet.iterator(); while(it.hasNext()) { String key = it.next(); //有了键就可以通过map集合的get()方法获取其对应的值 String value = map.get(key); System.out.println("key:" + key + ", value = " + value); } */ } }
练习1:每一个学生都有对应的归属地。学生Student,地址String。学生属性:姓名,年龄。注意:姓名和年龄相同的视为同一个学生。保证学生的唯一性。
分析:
- 描述学生。
- 定义Map容器,将学生作为键,地址作为值。存入。
- 获取map集合中的元素。
代码如下所示:
import java.util.HashMap; import java.util.Iterator; import java.util.Map; import java.util.Set; class Student implements Comparable<Student> { private String name; private int age; 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 obj) { if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student student = (Student) obj; return this.name.equals(student.name) && this.age == student.age; } @Override public int hashCode() { return name.hashCode() + age * 34; } public String toString() { return name + ":" + age; } @Override public int compareTo(Student s) { int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num == 0) return this.name.compareTo(s.name); return num; } } public class MapTest { public static void main(String[] args) { HashMap<Student, String> map = new HashMap<Student, String>(); map.put(new Student("lisi1", 21), "beijing"); map.put(new Student("lisi1", 21), "tianjin"); map.put(new Student("lisi2", 22), "shanghai"); map.put(new Student("lisi3", 23), "wuhan"); map.put(new Student("lisi4", 24), "nanjing"); //第一种取出方式 keySet() Set<Student> keySet = map.keySet(); Iterator<Student> it = keySet.iterator(); while(it.hasNext()) { Student s = it.next(); String address = map.get(s); System.out.println(s + "..." + address); } //第二种取出方式 entrySet() Set<Map.Entry<Student, String>> entrySet = map.entrySet(); Iterator<Map.Entry<Student, String>> it1 = entrySet.iterator(); while(it1.hasNext()) { Map.Entry<Student, String> me = it1.next(); Student stu = me.getKey(); String address = me.getValue(); System.out.println(stu + "..." + address); } } }
练习2:需求:对学生对象的姓名进行升序排序。
分析:因为数据是以键值对的形式存在的。所以要使用可以排序的Map集合。TreeMap。
代码:
import java.util.Comparator; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; class Student1 implements Comparable<Student1> { private String name; private int age; public Student1(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 obj) { if(!(obj instanceof Student1)) throw new ClassCastException("类型不匹配"); Student1 stu = (Student1) obj; return this.name.equals(stu.name) && this.age == stu.age; } @Override public int hashCode() { return name.hashCode() + age * 34; } public String toString() { return name + ":" + age; } @Override public int compareTo(Student1 s) { int num = new Integer(this.age).compareTo(new Integer(s.age)); if(num == 0) return this.name.compareTo(s.name); return num; } } class StuNameComparator implements Comparator<Student1> { @Override public int compare(Student1 s1, Student1 s2) { int num = s1.getName().compareTo(s2.getName()); if(num == 0) return new Integer(s1.getAge()).compareTo(new Integer(s2.getAge())); return num; } } public class MapTest1 { public static void main(String[] args) { Map<Student1, String> tm = new TreeMap<Student1, String>(new StuNameComparator()); tm.put(new Student1("blisi3", 23), "wuhan"); tm.put(new Student1("lisi1", 21), "beijing"); tm.put(new Student1("alisi4", 24), "nanjing"); tm.put(new Student1("lisi1", 21), "tianjin"); tm.put(new Student1("lisi2", 22), "shanghai"); //System.out.println(tm); Set<Map.Entry<Student1, String>> entrySet = tm.entrySet(); Iterator<Map.Entry<Student1, String>> it = entrySet.iterator(); while(it.hasNext()) { Map.Entry<Student1, String> me = it.next(); Student1 stu = me.getKey(); String addr = me.getValue(); System.out.println(stu + ":::" + addr); } } }
练习3:"sdfgzxcvasdfxcvdf"获取该字符串中的字母出现的次数。希望打印结果:a(1)c(2)...
分析:
通过结果发现,每一个字母都有对应的次数。说明字母和次数之间都有映射关系。注意:当发现有映射关系时,可以选择map集合。因为map集合中存放的就是映射关系。
问:什么时候使用map集合呢?
答:当数据之间存在着映射关系时,就要先想到map集合。
本题思路:
- 将字符串转换为字符数组。因为要对每一个字母进行操作。
- 定义一个Map集合,因为打印结果的字母有顺序,所以使用TreeMap集合。
- 遍历字符数组,将每一个字母作为键去查map集合。如果返回null,将该字母和1存入到map集合中。如果返回不是null,说明该字母在map集合中已经存在,并有对应次数。那么就获取该次数并进行自增,然后将该字母和自增后的次数存入到map集合中,覆盖掉原来键所对应的值。
- 将map集合中的数据变成指定的字符串返回。
代码:
import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.TreeMap; public class MapTest2 { public static void main(String[] args) { String s = charCount("sdf+gz-x,cvasdf1xcvdfkk"); System.out.println(s); } public static String charCount(String str) { char[] chs = str.toCharArray(); TreeMap<Character, Integer> tm = new TreeMap<Character, Integer>(); int count = 0; for(int i = 0; i < chs.length; i++) { if(!(chs[i] >= 'a' && chs[i] <= 'z' || chs[i] >= 'A' && chs[i] <= 'Z')) continue;//不是字母继续循环 Integer value = tm.get(chs[i]); if(value != null) { count = value; } count++; tm.put(chs[i], count); count = 0; /* if(value == null) { tm.put(chs[i], 1); } else { value = value + 1; tm.put(chs[i], value); } */ } //System.out.println(tm); StringBuilder sb = new StringBuilder(); 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(); Character ch = me.getKey(); Integer value = me.getValue(); sb.append(ch + "(" + value + ")"); } return sb.toString(); } }
map集合扩展知识——一对多关系
一对多的关系:一个学校有多个教室,每一个教室都有名称。一个教室有多个学生。
示例代码:
import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.List; /* map集合扩展知识。 map集合被使用是因为具备映射关系。 "yureban" StudentM("01" "zhangsan") "yureban" StudentM("02" "lisi") "jiuyeban" "01" "wangwu" "jiuyeban" "02" "zhaoliu" 一对多的关系 一个学校有多个教室,每一个教室都有名称。 一个教室有多个学生。 */ class StudentM { private String id; private String name; public StudentM(String id, String name) { this.id = id; this.name = name; } @Override public String toString() { return id + ":::" + name; } } public class MapDemo2 { public static void demo() { HashMap<String, List<StudentM>> czbk = new HashMap<String, List<StudentM>>(); List<StudentM> yure = new ArrayList<StudentM>(); List<StudentM> jiuye = new ArrayList<StudentM>(); czbk.put("yureban", yure); czbk.put("jiuyeban", jiuye); yure.add(new StudentM("01", "zhangsan")); yure.add(new StudentM("04", "wangwu")); jiuye.add(new StudentM("01", "zhouqi")); jiuye.add(new StudentM("02", "zhaoliu")); Iterator<String> it = czbk.keySet().iterator(); while(it.hasNext()) { String roomName = it.next(); List<StudentM> room = czbk.get(roomName); System.out.println(roomName); getInfos(room); } } public static void getInfos(List<StudentM> list) { Iterator<StudentM> it = list.iterator(); while(it.hasNext()) { StudentM s = it.next(); System.out.println(s); } } public static void main(String[] args) { demo(); /* HashMap<String, HashMap<String, String>> czbk = new HashMap<String, HashMap<String, String>>(); HashMap<String, String> yure = new HashMap<String, String>(); HashMap<String, String> jiuye = new HashMap<String, String>(); czbk.put("yureban", yure); czbk.put("jiuyeban", jiuye); yure.put("01", "zhangsan"); yure.put("02", "lisi"); jiuye.put("01", "zhaoliu"); jiuye.put("02", "wangwu"); //遍历czbk集合,获取所有的教室 Iterator<String> it = czbk.keySet().iterator(); while(it.hasNext()) { String roomName = it.next(); HashMap<String, String> room = czbk.get(roomName); System.out.println(roomName); getStudentMInfo(room); } //getStudentInfo(jiuye); */ } public static void getStudentInfo(HashMap<String, String> roomMap) { Iterator<String> it = roomMap.keySet().iterator(); while(it.hasNext()) { String id = it.next(); String name = roomMap.get(id); System.out.println(id + ":" + name); } } }