四、Map 接口
(一)、 Map 接口简介
Map接口储存一组成对的键--值对象,提供key(键)到value(值)的映射,Map中的key不要求有序,不允许重复。value同样不要求有序,但可以重复。最常见的Map实现类是HashMap,它的储存方式是哈希表,优点是查询指定元素效率高。
(二) 、Map 接口常用子类 HashMap 的相关操作
1 、向集合中增加和取出内容,代码如下 :
import java.util.Map;
import java.util.HashMap;
public class HashMapDemo01{public static void main(String args[]){Map<String,String> map = new HashMap<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");String val = map.get("A"); //根据key,取出valueSystem.out.print("key A对应的value值是 :" + val);}
}
程序运行结果 :
2 、判断指定的内容是否存在,代码如下 :
import java.util.Map;
import java.util.HashMap;
public class HashMapDemo02{public static void main(String args[]){Map<String,String> map = new HashMap<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");if(map.containsKey("B")){System.out.println("搜索的 key B 存在!");}else{System.out.println("搜索的 key B 不存在!");}if(map.containsValue("789")){System.out.println("搜索keyC的 value 存在!");}else{System.out.println("搜索keyC的 value 不存在!");}}
}
程序运行结果 :
3 、输出全部的 key,代码如下 :
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class HashMapDemo03{public static void main(String args[]){Map<String,String> map = new HashMap<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");Set<String> keys = map.keySet(); //Set集合指定的泛型类型要和Map中key的泛型类型一致Iterator<String> iter = keys.iterator();System.out.print("全部的 key :");while(iter.hasNext()){String str = iter.next();System.out.print(str + "、");}}
}
程序运行结果 :
4 、输出全部的 value,代码如下 :
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Collection;
public class HashMapDemo04{public static void main(String args[]){Map<String,String> map = new HashMap<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");Collection<String> values = map.values();Iterator<String> iter = values.iterator();System.out.print("全部的 value :");while(iter.hasNext()){String str = iter.next();System.out.print(str + "、");}}
}
程序运行结果 :
(三) 、旧的子类 :Hashtable
Hashtable 在 JDK 1.0版本就已存在,属于旧的类。其操作与 HashMap 基本一致,但在实际开发中,HashMap 使用更广泛。
import java.util.Map;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Collection;
import java.util.Set;
public class HashtableDemo01{public static void main(String args[]){Map<String,String> map = new Hashtable<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");Set<String> keys = map.keySet(); //Set集合指定的泛型要和Map中key的泛型类型一致Iterator<String> iter1 = keys.iterator();System.out.print("全部的 key :");while(iter1.hasNext()){String str = iter1.next();System.out.print(str + "、");}Collection<String> values = map.values();Iterator<String> iter2 = values.iterator();System.out.print("\n\n全部的 value :");while(iter2.hasNext()){String str = iter2.next();System.out.print(str + "、");}}
}
程序运行结果 :
(四) 、排序的子类 :TreeMap
前面程序在输出全部 key 的时候是无序的,而 TreeMap 子类的主要功能是可以按 key 排序。
import java.util.Map;
import java.util.TreeMap;
import java.util.Iterator;
import java.util.Set;
public class TreeMapDemo{public static void main(String args[]){Map<String,String> map = new TreeMap<String,String>();map.put("B","456");map.put("A","123");map.put("D","000");map.put("C","789");Set<String> keys = map.keySet(); Iterator<String> iter = keys.iterator();while(iter.hasNext()){String str = iter.next();System.out.println(str + "-->" + map.get(str));}}
}
程序运行结果 :
(五)、Map 接口的使用注意事项
1 、不能直接使用迭代输出Map 中的全部内容,因为Map 中存放的是一对值(key --> value),可通过 entrySet() 方法将 Map实例变为 Set接口对象,通过Map.Entry将 key --> value 分离,使用 Iterator 或 foreach 进行输出。
(1)使用 Iterator 输出 Map 实例 , 代码如下:
import java.util.Map;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
public class IteratorMapDemo01{public static void main(String args[]){Map<String,String> map = new HashMap<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");Set<Map.Entry<String,String>> allSet = map.entrySet(); //将 Map接口实例变为 Set接口实例Iterator<Map.Entry<String,String>> iter = allSet.iterator();while(iter.hasNext()){Map.Entry<String,String> me = iter.next(); //找到 Map.Entry 实例 System.out.println(me.getKey() + "-->" + me.getValue());}}
}
程序运行结果 :
(2)使用 foreach 输出 Map 实例 , 代码如下:
import java.util.Map;
import java.util.HashMap;
public class ForeachMapDemo01{public static void main(String args[]){Map<String,String> map = new HashMap<String,String>();map.put("A","123");map.put("B","456");map.put("C","789");for(Map.Entry<String,String> me : map.entrySet()){System.out.println(me.getKey() + "-->" + me.getValue());}}
}
程序运行结果 :
2 、 直接使用非系统类作为 key
在使用非系统类作为 key之前,先使用系统类作为 key 验证一下结果。以下程序代码使用 一个 "字符串" (系统类:String)表示key , 一个匿名对象 表示value 。观察其执行结果 :
import java.util.Map;
import java.util.HashMap;
class Person{private String name;private int age;public Person(String name,int age){this.name = name;this.age = age;}public String toString(){return "姓名 :" + this.name + ",年龄 :" + this.age ;}
}public class HashMapDemo05{public static void main(String args[]){Map<String,Person> map = new HashMap<String,Person>();map.put("ZiFuChaun",new Person("Tony",20));System.out.println(map.get("ZiFuChaun")); //通过 系统类key 查找 匿名对象value}
}
程序运行结果 :
以上程序使用系统类作为 key 可以查找到其对应 value的内容,那么当使用匿名对象(非系统类)作为key 时,观察结果 :
import java.util.Map;
import java.util.HashMap;
class Person{private String name;private int age;public Person(String name,int age){this.name = name;this.age = age;}public String toString(){return "姓名 :" + this.name + ",年龄 :" + this.age ;}
}public class HashMapDemo06{public static void main(String args[]){Map<Person,String> map = new HashMap<Person,String>();map.put(new Person("Tony",20),"ZiFuChaun");System.out.println(map.get(new Person("Tony",20))); }
}
程序运行结果 :
观察以上程序执行结果可以发现,使用匿名对象(非系统类)作为key,无法查找到指定内容,那么将对象实例化后再将其作为 key 时,观察程序结果 :
import java.util.Map;
import java.util.HashMap;
class Person{private String name;private int age;public Person(String name,int age){this.name = name;this.age = age;}public String toString(){return "姓名 :" + this.name + ",年龄 :" + this.age ;}
}public class HashMapDemo07{public static void main(String args[]){Map<Person,String> map = new HashMap<Person,String>();Person per = new Person("Tony",20); //实例化Person对象,再将其作为 keymap.put(per,"ZiFuChaun");System.out.println(map.get(per)); }
}
程序运行结果 :
观察以上程序执行结果可以发现,将对象实例化后再将其作为 key 时,可以查找到指定的内容,因为实例化后对象地址没有变化,所以可以找到。
如果想实现 直接使用非系统类作为 key找到对应的 value,就要依靠 覆写Object类中提供的 equals() 和 hashCode() 方法,以便区分是否是同一个对象 。代码如下 :
import java.util.Map;
import java.util.HashMap;
class Person{private String name;private int age;public Person(String name,int age){this.name = name;this.age = age;}//覆写equals()方法public boolean equals(Object obj){if(this==obj){return true;}if(!(obj instanceof Person)){return false;}Person p = (Person) obj;if(this.name.equals(p.name) && this.age == p.age){return true;}else{return false;}}//覆写hashCode()方法public int hashCode(){return this.name.hashCode() * this.age ;}public String toString(){return "姓名 :" + this.name + ",年龄 :" + this.age ;}
}public class HashMapDemo08{public static void main(String args[]){Map<Person,String> map = new HashMap<Person,String>();map.put(new Person("Tony",20),"ZiFuChaun");System.out.println(map.get(new Person("Tony",20))); }
}
程序运行结果 :
观察以上程序执行结果可以发现,如果 直接使用非系统类作为 key ,则对象所在的类中必须要 覆写 equals() 和 hashCode() 方法才能找到对应的 value
(六)、key 可以重复的 Map 集合 :IdentityHashMap
以上的 Map接口 操作中 key值是不能重复的,如果重复,则会覆盖之前的内容。此时可以使用 IdentityHashMap ,将相同的 key 添加到集合中,代码如下 :
import java.util.Map;
import java.util.IdentityHashMap;
import java.util.Iterator;
import java.util.Set;
class Person{private String name;private int age;public Person(String name,int age){this.name = name;this.age = age;}//覆写equals()方法public boolean equals(Object obj){if(this==obj){return true;}if(!(obj instanceof Person)){return false;}Person p = (Person) obj;if(this.name.equals(p.name) && this.age == p.age){return true;}else{return false;}}//覆写hashCode()方法public int hashCode(){return this.name.hashCode() * this.age ;}public String toString(){return "姓名 :" + this.name + ",年龄 :" + this.age ;}
}public class IdentityHashMapDemo{public static void main(String args[]){Map<Person,String> map = new IdentityHashMap<Person,String>();map.put(new Person("Jame",20),"ZiFuChaun_1");map.put(new Person("Jame",20),"ZiFuChaun_2");map.put(new Person("Tony",22),"jkl");Set<Map.Entry<Person,String>> allSet = map.entrySet();Iterator<Map.Entry<Person,String>> iter = allSet.iterator();while(iter.hasNext()){Map.Entry<Person,String> me = iter.next(); System.out.println(me.getKey() + "-->" + me.getValue());}}
}
程序运行结果 :
从以上程序执行结果可以发现,使用 IdentityHashMap,key值可以重复