Map概述
Map实现类:HashMap(默认)、TreeMap、Hashtable、properties、LinkedHashMap。
1 理解Map是什么
Set是单列表的表格。
List是两列的表格,其中一列是下标,另一列是元素。
Map是两列的表格,其中一列是key,另一列是value。
可以把List当成双列集合,其中一列为下标,另一列为元素。但下标不是由用户定义的,而是由List自动编号的。
可以把Map当成可以自定义下标的List,是真正的双列集合。其中key为自定义的下标,而value是元素。
因为List下标自动生成,所以一次添加一个元素。
因为Map需要自定义“下标”,所一次添加两个元素。
2Map的特性
l Map是双列集合;
l Map一次存储一对元素,其中一个是键,一个是值,键值有对应关系;
l Map中需要保证键是唯一的。
3Map和Collection比较
l Collection是单列集合,Map是双列集合;
l Collection一次添加一个元素,Map一次添加两个元素。
4Map和Entry
Map内部其实是多个Entry。
一个Entry中有两个属性:key和value。
Entry就是键值对对象。
我们说一个Map内部持有的就是Entry。而一个Entry有一个key和一个value
Map功能介绍
1 测试put()、putAll()和toString()方法
l V put(K key, V value) -- 添加一个键值对到当前map中。
l void putAll(Map map) -- 添加一个map到当前map中。
l String toString() – 把map转换成字符串。
2 测试put()不能有重复的key,但可以有重复的value
多次put(),其中如果key是相同的,那么会覆盖原来的值。
3 测试获取方法
l V get(K) -- 获取指定键的值。
l int size() – 获取键值对的个数。
l Set<K> keySet() -- 获取所有键(遍历获取),值不能重复,所以使用Set返回值类型。
l Collection<V> value() -- 获取所有值。值可以重复,所以使用Collection返回值类型。
l Set<Map.Entry<K,V>> entrySet() -- 返回当前Map中所有键值对。
4 测试其它方法
l boolean containsKey(Object key) -- 判断是否存在指定的键。(判断)
l boolean containsValue(Object value) -- 判断是否存在指定的值。(判断)
l boolean isEmpty() -- 判断是否为空映射。(判断)
l void clear() --清空所有键值对。(删除)
l V remove(K) -- 通过键删除一个键值对,返回值为被删除的键值对中的值。(删除)
遍历Map
1 遍历Map的键
Set<K> keyset();
2 遍历Map的值
Collection<V> values();
3 通过键遍历Map
public static void fun1() { Map<String,String> map = new HashMap<String, String>(); map.put("1", "一"); map.put("2", "二"); map.put("3", "三"); map.put("4", "四"); map.put("5", "五"); // 获取所有键 Set<String> keys = map.keySet(); // 增强for遍历Set for(String key : keys) { // 通过键获取值 String value = map.get(key); System.out.println(key + "=" + value); } } |
4 通过Entry遍历Map
public static void main(String[] args) { Map<String,String> map = new HashMap<String, String>(); map.put("1", "一"); map.put("2", "二"); map.put("3", "三"); map.put("4", "五"); map.put("5", "五"); // 获取所有键值对(Entry) Set<Map.Entry<String, String>> entrys = map.entrySet(); // 遍历Set for(Map.Entry<String, String> entry : entrys) { String key = entry.getKey(); String value = entry.getValue(); System.out.println(key + "=" + value); //System.out.println(entry); } } |
HashMap
1HashMap特性
l 底层使用哈希表结构
l 无序!
l 线程不安全的!
l 对于常用方法可以保证稳定的性能!
l 因为使用哈希表,所以键元素类型必须重写equals()和hashCode()方法
2HashMap没有独有方法
HashMap没有独有方法,所有方法都是从Map继承而来。
3 测试HashMap<Person,Person>
要求键类型(Person)必须重写equals()和hashCode()方法
Hashtable
基本不使用!
1Hashtable和HashMap比较
l Hashtable是1.0的老版本类,是线程安全的,键和值都不能为null;
l HashMap是1.2的新版本类,是线程不安全的,键和值都可以为null;
2 测试Hashtable的遍历
public static void main(String[] args) { Hashtable<String,String> map = new Hashtable<String, String>(); map.put("name", "zhangSan"); map.put("sex", "male"); map.put("age", "22"); //map.put(null, "呵呵"); //System.out.println(map); // keySet()这个方法是Map接口的 // 获取所有键,返回的是Set类型 Set<String> keys = map.keySet(); // 遍历所有键 for(String key : keys) { // 通过当前的key获取相应的value String value = map.get(key); System.out.println(key + "=" + value); } // 可以不在使用了! // 获取所有键,但返回的值是枚举器 // keys()是Hashtable独有的方法 // 返回的是所有键,但类型为Enumeration Enumeration<String> e = map.keys(); // 遍历Enumeration while(e.hasMoreElements()) { // 获取Enumeration中的一个key String key = e.nextElement(); // 通过key获取相应的value String value = map.get(key); System.out.println(key + "=" + value); } } |
Properties
很很有用!
1Properties特性
l 1.0的老版本类
l Hashtable的子类(线程安全的、底层哈希表、键值都不能为null)
l 有自己的映射获取方法,不建议使用父类的映射获取方法
l 可以与IO流交互(很强大的功能)
2Properties独有方法
l Object setProperty(String name, String value):代替父类的put()方法来映射值;
l String getProperty(String name):代替父类的get()方法;
l Enumeration<?> propertyNames():获取所有键。
3 测试Properties的遍历
LinkedHashMap
LinkedHashMap与HashMap的关系,与LinkedHashSet与HashSet的关系相似。
1LinkedHashMap的特性
l HashMap的子类
l 没有独有方法
l 保证元素迭代顺序与添加顺序相同
l 好比LinkedHashSet与HashSet的关系
2 测试LinkedHashMap的遍历
public static void main(String[] args) { Map<String, String> map = new LinkedHashMap<String, String>(); map.put("1", "壹"); map.put("2", "贰"); map.put("3", "叁"); map.put("4", "肆"); map.put("5", "伍"); // 直接使用toString()打印 System.out.println(map); // 获取所有键:类型是Set Set<String> keys = map.keySet(); // 通过Set获取迭代器 Iterator<String> it = keys.iterator(); // 遍历迭代器 while(it.hasNext()) { // 获取一个键 String key = it.next(); // 通过键获取值 String value = map.get(key); // 打印 System.out.println(key + "=" + value); } // 获取所有值也是有序的! Collection<String> coll = map.values(); System.out.println(coll); } |
TreeMap
1TreeMap的特性
l 底层使用二叉树结构;
l 有序!使用键类型的自然顺序,或者TreeMap的比较器排序;
l 使用TreeMap要求键类型有自然顺序,或者给TreeMap提供比较器;
2TreeMap键类型为String
3TreeMap键类型为Person(自定义类型)
练习
1 候选人投票统计
一共三个候选人:zhangSan、liSi、wangWu
投票结果使用一个字符串表示:zhangSan liSi liSi zhangSan liSi wangWu liSi liSi liSi zhangSan。
程序统计每个名候选人的得票结果:zhangSan得3票、liSi得6票、wangWu得1票。
分析:
1 使用Map来完成,候选人名字为key,票数为value。
2 把字符串分割成字符串数组。
3 当获取一个名字后,判断Map是否存在这个名字为key的键值对
4 如果存在,那么就把value获取,然后再把value++,再把新的键值对放到Map中,这样就替换了原来的键值对;
5 如果不存在,那么就直接put(),票数为1。
6 循环遍历Map
2 明教结构图
明教:
l 光明使者
Ø 光明左使:杨逍;
Ø 光明右使:范遥。
l 护教法王
Ø 紫衫龙王:黛绮丝;
Ø 白眉鹰王:殷天正;
Ø 金毛狮王:谢逊;
Ø 青翼蝠王:韦一笑。
把明教定义为一个Map。
分析:
光明左使:这是一个Map<String,String>
护教法王:这是一个Map<String,String>
明教是一个Map<String,Map>,其中key是String,而value是Map。更准确的说,明教是Map<String,Map<String,String>>类型。