集合之Map
来源:互联网 发布:2017淘宝活动大全 编辑:程序博客网 时间:2024/06/07 19:01
已实现的子类:
1、HashMap
底层数据结构是哈希表,可以存放null键和null值,该集合是线程不同步的,效率高,jdk1.2出现。
2、HashTable
底层数据结构是哈希表,不可以存放null键和null值,该集合是线程同步的,效率低,jdk1.0出现。
3、TreeMap
底层是二叉树数据结构,线程不同步,可以用于给Map中的键进行排序。
Map中取元素的方式:
1、Map中的取出方式
(1)Map.Entry:这是一种描述键值对之间的映射关系的一种特殊数据类型,可以指定泛型,而Entry接口是Map接口的一个静态子接口,又称为映射项,意指在Map存在后用来表示Map中键值的关系,而Map.Entry接口通常被一个内部类实现。。。。。通过map的entrySet方法来获取Map.Entry类型的Set集合,然后通过Set迭代器来获取Map.Entry对象,用这个对象调用其内部的getKey和getValue方法获取建和值。
(2)通过keySet方法获得一个存取key的Set集合,然后通过map的getKey方法获取这些键,通过map的get(key)方法获取对应的值。
下面用一个例子来实现这两种方法
exp1:
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) { // TODO 自动生成的构造函数存根 this.name = name; this.age = age; } public String getName() { return name; } public int getAge() { return age; } @Override public String toString() { // TODO 自动生成的方法存根 return super.toString(); } //重写compareTo方法自定义排序规则 @Override public int compareTo(Student s) { // TODO 自动生成的方法存根 int num = new Integer(this.getAge()).compareTo(new Integer(s.getAge())); System.out.println(this.name+"-compareTo-"+s.getName()); if(num == 0) return this.getName().compareTo(s.getName()); return num; } //重写hashCode方法 @Override public int hashCode(){ // TODO 自动生成的方法存根 return name.hashCode()+age*32; } //重写equals方法自定义元素唯一性标准 @Override public boolean equals(Object obj) { // TODO 自动生成的方法存根 if(!(obj instanceof Student)) throw new ClassCastException("类型不匹配"); Student s = (Student) obj; return this.name.equals(s.name)&&this.age == s.age; } }public class MapTest1 { public static void main(String[] args) { Map<Student,String> map = new HashMap<Student,String>(); map.put(new Student("张三", 18), "上海"); map.put(new Student("李四", 19), "西安"); map.put(new Student("王五", 20), "火星"); /* //第一种取出方式 Set<Student> keySet = map.keySet(); Iterator<Student> it = keySet.iterator(); while(it.hasNext()){ Student s = it.next();//key String attr = map.get(s); System.out.println(s.getName()+"-"+s.getAge()+":"+attr); } */ //第二种取出方式 Set<Map.Entry<Student, String>> set = map.entrySet(); for(Iterator<Map.Entry<Student, String>> it = set.iterator();it.hasNext();) { Map.Entry<Student, String> entry = it.next(); Student s = entry.getKey(); String attr = entry.getValue(); System.out.println(s.getName()+"-"+s.getAge()+":"+attr); } }}
看完这两种方法后再看一下这个例子中重写了equals和hashCode方法,当要指定元素唯一性时可能要涉及多个方面,而equals方法本身比较的是某个对象的一项内容,比如Integer和String对象,因此需要重写。然后重写hashCode方法保证元素唯一性主要是以实例为主,而不是对象本身,比如两个不同的对象拥有不同的哈希码直接存入,但此时实例却相同,从而省略了equals方法判断这一步,导致与实际情况不符。
但为什么要重写compareTo方法呢?因为当有多个对象要被存储时,此时存储的容器就有了多种选择,可以是哈希表、二叉树、数组等等,如果将多个对象存入了二叉树中,元素就必须被赋予排序规则,否则会抛出异常,所以为了保险起见需要定义比较器,通过实现Comparable或Comparator接口均可。
由于Map本身也是一个对象,而对象可以作为元素存到集合中,所以Map中也可以嵌套,当然该内部Map对象也可以根据其键值对的含义将其封装为一个类,然后将该类对象存入。下面通过两个例子说明这两种方法。
exp2:
import java.util.HashMap;import java.util.Iterator;/* * Map之间的嵌套 */public class MapTest1 { public static void main(String[] args) { HashMap<String,HashMap<Integer,String>> school = new HashMap<String,HashMap<Integer,String>>(); HashMap<Integer,String> class1 = new HashMap<>(); HashMap<Integer,String> class2 = new HashMap<>(); school.put("普通班", class1); school.put("火箭班", class2); class1.put(1, "张三"); class1.put(2, "李四"); class2.put(1, "王五"); class2.put(2, "赵六"); Iterator<String> it1 = school.keySet().iterator(); while(it1.hasNext()){ String cla = it1.next();//取班级的key HashMap<Integer, String> claMap = school.get(cla);//取班级的值 System.out.println(cla); Iterator<Integer> it2 = claMap.keySet().iterator(); while(it2.hasNext()){ int num = it2.next(); String name = claMap.get(num); System.out.println(num+"::"+name); } } }}
exp3:
import java.util.ArrayList;import java.util.HashMap;import java.util.Iterator;import java.util.List;/* * Map存入对象 * */public class MapTest2 { public static void main(String[] args) { HashMap<String, List<Student>> school = new HashMap<String,List<Student>>(); List<Student> rClass = new ArrayList<Student>(); List<Student> nClass = new ArrayList<Student>(); school.put("普通班", nClass); school.put("火箭班", rClass); nClass.add(new Student(1,"王五")); nClass.add(new Student(2,"赵六")); rClass.add(new Student(1,"张三")); rClass.add(new Student(2,"李四")); Iterator<String> it = school.keySet().iterator(); while(it.hasNext()){ String className = it.next(); List<Student> list = school.get(className); System.out.println(className); for(Student item : list){ System.out.println(item.getNum()+"::"+item.getName()); } } }}class Student{ private String name; private int num; public Student(int num,String name) { this.name = name; this.num = num; } public String getName() { return name; } public int getNum() { return num; }}
对于TreeMap,如果存入对象并没有自然顺序或要按照给定顺序排序,必须要定义一个比较器来使元素有自然顺序,下面通过一个例子说明。
exp4:
import java.util.Comparator;import java.util.Iterator;import java.util.Map;import java.util.Set;import java.util.TreeMap;/* * * 输入一个字符串,打印每个字符以及出现的次数并使字符倒序排序 * 输出格式为:字符(次数)字符(次数)... * * 思路:(1)将字符串中的字符存到一个数组中,然后对数组遍历,如果当前元素在TreeMap中不存在 * 那么添加进去,并将该元素和其出现次数作为一对键值对;如果当前元素已存在,定义一个 * 累加器,在已存在次数基础上自加一次再存入TreeMap中,由于key值相同,所以以前的 * 记录将会被更新,第一种情况也是如此,只不过累加器是从零开始的。最后按照给定格式取出 * 存在Map中的元素。 * (2)创建比较器自定义比较规则 */public class TreeMapTest { public static String charCount(String str){ char[] ch = str.toCharArray(); TreeMap<Character, Integer> treeMap = new TreeMap<>(new Compare()); int count = 0; for(int i=0;i<ch.length;i++){ if(!(ch[i]>='a'&&ch[i]<='z'||ch[i]>='A'&&ch[i]<='Z')) continue; Integer value = treeMap.get(ch[i]); if(value!=null) count=value; count++; treeMap.put(ch[i], count); count=0; } //System.out.println(treeMap); StringBuffer sb = new StringBuffer(); Set<Map.Entry<Character, Integer>> set = treeMap.entrySet(); Iterator<Map.Entry<Character, Integer>> it = set.iterator(); while(it.hasNext()){ Map.Entry<Character, Integer> entry = it.next(); sb.append(entry.getKey()+"("+entry.getValue()+")"); } return sb.toString(); } public static void main(String[] args) { String str = charCount("aababcabcd"); System.out.println(str); } }//定义一个比较器,使字符按照原有顺序的倒序排列class Compare implements Comparator<Object>{ @Override public int compare(Object obj1,Object obj2) { // TODO 自动生成的方法存根 if(!(obj1 instanceof Character)||(obj2 instanceof Character)) { Character ch1 = (Character) obj1; Character ch2 = (Character) obj2; int result = ch1.compareTo(ch2); if(result>0) return -1; else if(result<0) return 1; return 0; } throw new RuntimeException("类型不匹配"); }}
- 集合框架之Map集合
- Java集合之-Map集合
- 集合框架之map
- java之Map集合
- 集合框架之Map
- 集合框架之Map
- Java集合之Map
- Java集合之Map
- Java集合之Map
- Java集合之Map
- JAVA 集合之MAP
- java集合之Map
- java 集合之Map
- Java集合之Map
- Java集合之Map
- Java集合之Map
- Java集合之Map
- java集合之Map
- 关于 MySQL 你可能不知道的 SQL 使用技巧
- MFC学习(01) 矩形框选择移动三角形 (VS2015版本)
- AngularJS系列——对象详解
- Java新特性之可变参数
- 解决mysql-5.7.18安装,MySQL服务无法启动
- 集合之Map
- 基于Raspbian(树莓派)搭建web安全练习环境(一)
- Sublime Text 3 快捷键汇总
- Log4J的基本配置
- Unable to retrieve metadata for procedure
- 适合做程序员的人:像机器一样思考
- Nim游戏
- LeetCode 200. Number of Islands (并查集)
- 探索Android调用系统的分享功能