首页 > 学院 > 开发设计 > 正文

集合框架之Map集合

2019-11-14 12:50:21
字体:
来源:转载
供稿:网友

今天,我向大家介绍集合框架的最后一个知识块:Map集合,Map集合是双列集合的根接口。我个人感觉Map集合比Collection集合更重要些,在实际的项目开发中,使用Map创建集合非常之多,在框架整合开发中也会用到,在后期做Web项目的时候还会用到它,原因我不多说。接下来直接看我演示Map集合的案例…在前面我说到了Collection集合,Collection集合是单列集合的根接口,我们学习了Collection集合的Set集合和List集合,又介绍和学习了Set集合的子集合:HashSet、LinkedHashSet和TreeSet,主要说了它们的功能和用途,学习了List集合的子集合:ArrayList、LinkedList和Vector,也介绍它的功能和用途,但其中最重要的是要学会怎样去应用,该如何用?嘿嘿,前面的介绍和学习那就慢慢领悟吧~接下来,步入我们的正题:介绍和学习Map集合。 首先,Map集合它也是一个接口,上面刚说到,它是双列集合的根接口。关于Map集合接口的概述,百度了一下,网上说的是千篇一律。我从Sun官方提供的手册中,查看API可知: Map集合是:1.将键映射到值得对象;2.是一个集合不能包含重复的键;3.每个键最多只能映射到一个值。 那Map接口与Collection接口有什么不同呢? 1.Map接口是双列的,而Collection接口是单列的; 2.Map的键唯一,Collection的子体系Set是唯一的; 3.Map集合的数据结构针对键有效,跟值无关,Collection集合的数据结构针对元素有效。 Map集合它处于java.util包下,它的数据结构看起来更像多行两列的表格,每一条数据中包含两个信息key-value,其中key在Map中不允许重复,重复指的是equals为true,Map集合它有两个子类,一个是HashMap,一个是TreeMap,HashMap有一个子类叫做LinkedHashMap。和Set集合的体系结构非常相似。接下来,我们来看一下Map集合的方法: 1.V put(K k,V v):向Map集合中添加元素 如果键是第一次存储,就直接存储元素,返回null; 如果键不是第一次存储,就用值把以前的值替换掉,返回以前的值。 如下程序代码:

package cn.edu.jit.map;import java.util.HashMap;import java.util.Map;/** * Map * 该数据结构看起来更像多行两列的表格 * 每一条数据中包含两个信息key-value, * 其中key在Map中不允许重复,重复指的是equals为true。 * @author Rocky * */public class MapDemo01 { public static void main(String[] args) { /* * Map本身也是一个接口,是不能实例化的,我们用它的一个 * 实 * 例叫做:HashMap * 我们通常也让Map加泛型,给它们的具体类型。 * * * 创建一个Map * key是字符串,value是整数 */ Map<String,Integer> map = new HashMap<String,Integer>(); //调用Map的一个方法叫 put() 可以存放key和value的值。 /* * V put(K k,V v) * 将给定的key与对应的value存入Map中。 * * 若给定的key在Map中不存在,则是添加新内容,那么返回的就是被替换的value值。 * 若给定的key在Map中已存在,则是替换value操作,返回值是null。 * */ System.out.PRintln(map);//{} Integer i = map.put("语文", 95); System.out.println(map);//{语文=95} System.out.println(i);//null i = map.put("语文", 99); System.out.println(map);//{语文=99} map.put("英语", 90); map.put("数学", 90); map.put("物理", 98); map.put("化学", 88); System.out.println(map); }}

从Map中获取元素的方式,我们采用Map的get()方法。 2.V get(K k):根据给定的key获取对应的value值。 如下程序代码:

/* * V get(K k) * 根据给定的key获取对应的value值 */ Integer num = map.get("英语"); System.out.println("英语" + num); //如果给一个不存在的key,其结果如下: /* * 给定一个Map中不存在的key, * 返回值则为null。 */ num = map.get("高数"); System.out.println("高数:" + num);//若找不到对应的key值,则返回null"空"

3.删除功能: void clear():移除所有的键值对元素; V remove(Object key):根据键删除键值对元素,并把值返回。 如下程序代码:

package cn.edu.jit.map;import java.util.HashMap;import java.util.Map;public class MapDemo02 { public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); //根据键删除元素,返回键对应的值 Integer value = map.remove("张三"); System.out.println(value); System.out.println(map); //运行结果: //23 //{赵六=26, 李四=24, 王五=25} }}

4.判断功能: boolean containsKey(K k): 判断当前Map中是否含有给定的key,是否含有是根据key的equals判断的,返回值为boolean类型。 boolean containsValue(Object value): 判断集合是否包含指定的值,返回值为boolean类型。 boolean isEmpty(): 判断集合是否为空,返回值为boolean类型。 如下代码程序:

package cn.edu.jit.map;import java.util.HashMap;import java.util.Map;public class MapDemo03 { public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); //根据键删除元素,返回键对应的值// Integer value = map.remove("张三");// System.out.println(value); /* * 判断是否包含传入的键(值) */ System.out.println(map.containsKey("张三"));//true System.out.println(map.containsValue(23));//true System.out.println(map); }}

5.int size():返回集合中的键值对的个数 如下程序代码:

package cn.edu.jit.map;import java.util.Collection;import java.util.HashMap;import java.util.Map;public class MapDemo04 { public static void main(String[] args) { Map<String, Integer> map = new HashMap<String, Integer>(); map.put("张三", 23); map.put("李四", 24); map.put("王五", 25); map.put("赵六", 26); Collection<Integer> c = map.values(); System.out.println(c);//[26, 23, 24, 25] System.out.println(map.size());//4 }}

上面几个方法主要是Map集合的常用方法,接下来我们看hashCode对Map操作的影响,看如下程序代码:

package cn.edu.jit.map;import java.util.HashMap;import java.util.Map;/** * hashCode对Map操作的影响 * @author Rocky * */public class MapDemo02 { public static void main(String[] args) { Map<Point,Integer> map = new HashMap<Point,Integer>(100); Point p = new Point(1,2); map.put(p, 100); boolean contains = map.containsKey(p); System.out.println("包含key:" + contains); System.out.println(map); Integer i = map.get(p); System.out.println(i); System.out.println(p.hashCode()); //内容变化了,hashCode值就会变化 p.setX(2); System.out.println(p.hashCode()); i = map.get(p); System.out.println(i);//null contains = map.containsKey(p); System.out.println("包含key:" + contains);//包含key:false System.out.println(map);//{day05.Point@401=100} map.put(p, 200); System.out.println(map); Integer ii = map.remove(p); System.out.println("删除的是:" + ii); System.out.println(map); p.setX(1); ii = map.remove(p); System.out.println("删除的是:" + ii);//null System.out.println(map);//{day05.Point@401=100} }}

使用HashMap时应当注意,作为key的对象有以下要求: 1.首先当key这个类重写了equals方法,那么重写的hashcode的要求必须满足; 2.作为key的对象若存入HashMap后,其会影响hashcode值得内容不要发生改变,否则可能会影响Map操作。 下面,我给大家主要介绍遍历Map的三种方式: 1.遍历所有的key; 2.遍历所有的键值对(key-value); 3.遍历所有的value(不常用) 如下程序代码:

package cn.edu.jit.map;import java.util.Collection;import java.util.HashMap;import java.util.LinkedHashMap;import java.util.Map;import java.util.Set;import java.util.Map.Entry;/** * 遍历Map的三种方式: * 1:遍历所有的key * 2:遍历所有的键值对(key-value) * 3:遍历所有的value(不常用) * @author Rocky * */public class MapDemo03 { public static void main(String[] args) { Map<String,Integer> map = new LinkedHashMap<String,Integer>(); map.put("数学", 90); map.put("语文", 98); map.put("物理", 85); map.put("化学", 78); map.put("英语", 92); map.put("体育", 65); map.put("生物", 78); /* * 遍历所有的key * Set<K> keySet() * 该方法可以获取Map中所有的Key,并将它们存入一个Set集合中返回 * 所以,遍历该集合就等于遍历所有的key了。 */ Set<String> keySet = map.keySet(); for(String str : keySet) { System.out.println("str:" + str); } /* * 遍历键值对 * Set<Entry> entrySet() * 该方法会将每一组key-value存入一个Entry示例中,并将 * 这些Entry实例存入一个Set集合并返回 * 我们只需要遍历该集合,拿到每一个Entry实例并获取其中的key与 * value即可。 * * Entry是Map的一个内部类。 */ //我们Entry里面的泛型儿要和Map中的泛型保持一致! Set<Entry<String,Integer>> entrySet = map.entrySet(); for(Entry<String,Integer> e:entrySet) { String key = e.getKey(); Integer value = e.getValue(); System.out.println(key+":"+value); } /* * 遍历所有的value * 获取来的是Collection集合 */ Collection<Integer> values = map.values(); for(Integer value : values) { System.out.println("value:" + value); } }}

下面,我们来做一个案例练习:HashMap集合键是Student,值是String。 为什么我们要在双列集合中要存储一个Student呢,Student是什么?它是一个自定义类。也就是我们想把自定义对象存储在HashMap集合中。刚在一开始的时候我就介绍过,HashMap这个指针指向的只对键有效,咱们把自定义对象存储在它的键的位置,就想看它如何保证键的唯一。接下来,我们来演示这个案例,看如下程序代码: 首先,我们要自定义一个Student类:

package cn.edu.jit.bean;public class Student { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); 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 String toString() { return "Studnet [age=" + age + ", name=" + name + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; }}

我们创建一个HashMapDemo05,如下程序:

package cn.edu.jit.map;import java.util.HashMap;import cn.edu.jit.bean.Student;/** * 案例演示: * HashMap集合键是Student,值是String的案例。 * 键:是学生对象,代表每一个学生; * 值:是字符串对象,代表学生的归属地 * @author Rocky * */public class HashMapDemo05 { public static void main(String[] args) { HashMap<Student, String> hm = new HashMap<Student, String>(); hm.put(new Student("钱春华",23), "江苏南通"); hm.put(new Student("Jolin",24), "江苏泰州"); hm.put(new Student("Jolin",24), "上海"); hm.put(new Student("二狗",25), "江苏无锡"); hm.put(new Student("瑶瑶",20), "江苏南京"); System.out.println(hm); //{Studnet [age=23, name=钱春华]=江苏南通, Studnet [age=25, name=二狗]=江苏无锡, Studnet [age=20, name=瑶瑶]=江苏南京, Studnet [age=24, name=Jolin]=上海} }}

接下来,我们来说HashMap有一个子类叫做LinkedHashMap,它的特点是:底层是链表实现的可以保证怎么存就怎么取。如下代码:

package cn.edu.jit.map;import java.util.LinkedHashMap;/** * * @author Rocky * */public class LinkedHashMapDemo { public static void main(String[] args) { LinkedHashMap<String, Integer> lhm = new LinkedHashMap<String, Integer>(); lhm.put("张三", 23); lhm.put("李四", 24); lhm.put("赵六", 26); lhm.put("王五", 25); System.out.println(lhm); //{张三=23, 李四=24, 赵六=26, 王五=25} }}

说完了LinkedHashMap,我们再来说一说TreeMap,我们来看看TreeMap如何对键唯一,因为双列集合只针对键有效,键值得算法是一个二叉树,也就是说它可以对键进行排序。好,我们来通过这个案例演示TreeMap集合:键是Student,值是:String。如下程序代码: 首先我们要在Student类实现Comparable接口,并重写compareTo方法,贴上代码:

@Override public int compareTo(Student o) { int num = this.age - o.age; return num == 0 ? this.name.compareTo(o.name) : num; }

Student类整个代码如下:

package cn.edu.jit.bean;public class Student implements Comparable<Student> { private String name; private int age; public Student() { super(); } public Student(String name, int age) { super(); 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 String toString() { return "Studnet [age=" + age + ", name=" + name + "]"; } @Override public int hashCode() { final int prime = 31; int result = 1; result = prime * result + age; result = prime * result + ((name == null) ? 0 : name.hashCode()); return result; } @Override public boolean equals(Object obj) { if (this == obj) return true; if (obj == null) return false; if (getClass() != obj.getClass()) return false; Student other = (Student) obj; if (age != other.age) return false; if (name == null) { if (other.name != null) return false; } else if (!name.equals(other.name)) return false; return true; } @Override public int compareTo(Student o) { int num = this.age - o.age; return num == 0 ? this.name.compareTo(o.name) : num; }}

在创建一个TreeMapDemo类,代码如下:

package cn.edu.jit.map;import java.util.TreeMap;import cn.edu.jit.bean.Student;/** * TreeMap集合键是Student,值是String * @author Rocky * */public class TreeMapDemo { public static void main(String[] args) { TreeMap<Student, String> tm = new TreeMap<Student, String>(); tm.put(new Student("张三",23), "北京"); tm.put(new Student("李四",24), "上海"); tm.put(new Student("王五",25), "广州"); tm.put(new Student("赵六",26), "深圳"); System.out.println(tm); //在没有实现Comparable接口时,报了异常,因为没有在Student类实现Compare这个接口。 //运行结果:{Studnet [age=23, name=张三]=北京, Studnet [age=24, name=李四]=上海, Studnet [age=25, name=王五]=广州, Studnet [age=26, name=赵六]=深圳} }}

大家觉得很好奇,刚才运行结果的程序是按照对象比较性进行排序的,有没有比较器呢,我们来看一下,有一个重构方法Comparator去实现,我们通过匿名内部类去实现,贴上代码:

package cn.edu.jit.map;import java.util.Comparator;import java.util.TreeMap;import cn.edu.jit.bean.Student;/** * TreeMap集合键是Student,值是String * @author Rocky * */public class TreeMapDemo { public static void main(String[] args) { TreeMap<Student, String> tm = new TreeMap<Student, String>(new Comparator<Student>() { @Override public int compare(Student s1, Student s2) { //按照姓名去比较 int num = s1.getName().compareTo(s2.getName()); return num == 0 ? s1.getAge() - s2.getAge() : num; } }); tm.put(new Student("张三",23), "北京"); tm.put(new Student("李四",24), "上海"); tm.put(new Student("王五",25), "广州"); tm.put(new Student("赵六",26), "深圳"); System.out.println(tm); //运行结果:{Studnet [age=23, name=张三]=北京, Studnet [age=24, name=李四]=上海, Studnet [age=25, name=王五]=广州, Studnet [age=26, name=赵六]=深圳} //我们可以看到,这就按照顺序排序打印出来了 }}

好了,今天Map集合方法以及它的用途就介绍到这,下面讲解HashMap集合嵌套,本文中所有的案例程序都是本人亲测过,如有不对的地方请各位朋友欢迎指正,谢谢了!


发表评论 共有条评论
用户名: 密码:
验证码: 匿名发表