之前说的Set(HashSet、TreeSet)接口和List(ArrayList、Vector、LinkedList)接口都是对单值别的操作,即每次只能操作一个对象。
Map接口与他们不同的是每次操作一对对象,Map中每个元素都使用“key----->value”的形式存储在集合中。
public interface Map<K,V>
1、Map.Entry接口
Map.Entry接口是Map内部定义的一个接口,专门用来保存key--->Value的内容,是static关键字声明的内部接口。
public static interface Map.Entry<K,V>
我们知道,在Map接口的操作中,所用的内容都是通过key--->Value的形式保存数据的,那么对于集合来讲,实际上将“key---->value”的数据保存在了Map.Entry接口的实例后,再在Map集合中插入一个Map.Entry的实例化对象,如下图所示:
一般在Map操作中(增加、取出数据)用户不用关心Map.Entry,但是将Map中的数据全部输出时必须使用Map.Entry,随后介绍。
本节主要介绍常用的子类:
HashMap:无序存放,新的操作类,key不允许重复。
HashTable:无序存放,旧的操作类,key不允许重复。
TreeMap:可排序map集合,按集合中key排序,key不允许重复。
WeakHashMap:弱引用Map集合,集合中某些内容不再使用时清除,使用gc回收。
IndentityHashMap:key可以重复的map集合。
2、HashMap
(1)向集合中增加和取出内容
put(K key, V value);增加
get(Object K)根据key找到对应的内容value
public class HashMapDemo01 {
/**
* Map接口中使用put增加内容,使用get(Object Key)根据Key找到内容value
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1", "www.bupt.cn");
map.put("2", "www.baidu.cn");
map.put("3", "www.haha.cn");
String str = map.get("1");
System.out.println("取得的内容是:"+str);
}
}
输出结果为:
取得的内容是:www.bupt.cn
(2)判断指定的key或value是否存在
contains(Object key);
contains(Object value);
public class HashMapDemo06 {
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1", "www.bupt.cn");
map.put("2", "www.baidu.com");
map.put("3", "www.haha.com");
if(map.containsKey("2")){
System.out.println("搜索的key存在");
}else{
System.out.println("搜索的key不存在");
}
if(map.containsValue("www.souhu.com")){
System.out.println("搜索的value存在");
}else{
System.out.println("搜索的value不存在");
}
}
}
输出结果:
指定的key存在
指定的value不存在
(3)输出全部的key
Map接口中提供了一个keySet()的方法,可以将一个Map中的全部key变成一个Set集合,一旦有了Set接口实例,就可以直接使用Iterator接口进行输出。操作时注意接收的Set集合中指定的泛型要和Map中key的泛型类型一致。
public class HashMapDemo02 {
/**
* 输出全部的Key
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1","www.bupt.cn");
map.put("2", "www.baidu.cn");
map.put("3", "www.haha.cn");
Set<String> keys = map.keySet();//得到全部的Key,放入set集合
Iterator<String> iter = keys.iterator();//实例化Iterator
System.out.print("全部的Key:");
while(iter.hasNext()){
String str = iter.next();
System.out.print(str+"、");
}
}
}
输出结果:
全部的Key:1、2、3、
(4)输出全部的value
使用values()方法,返回Collection类型。使用时同样注意泛型的类型。
public class HashMapDemo03 {
/**
* 输出全部的value
*/
public static void main(String[] args) {
Map<String,String> map = new HashMap<String,String>();
map.put("1", "www.bupt.cn");
map.put("2", "www.baidu.com");
map.put("3", "www.haha.com");
Collection<String> coll = map.values();//得到全部的value,放入Collection
Iterator<String> iter = coll.iterator();//实例化Iterator
System.out.print("全部的value:");
while(iter.hasNext()){
String str = iter.next();
System.out.print(str+"、");
}
}
}
输出结果:
全部的value:www.bupt.cn、www.baidu.com、www.haha.com、
2、HashTable
HashTable与vector类的推出时间一样,都属于旧的操作类,使用上没有太大区别。
性能:HashMap异步处理,性能高;HashTable同步处理,性能低。
线程安全:HashMap非线程安全;HashTable线程安全。
空键:允许Key设置为null;HashTable不允许将Key设置为null,否则出现Null Pointer Exception异常
实际开发中HashMap类使用较多。
3、TreeMap
之前的HashMap、HashTable存放数据时并没有对其进行排序。
TreeMap子类的主要特点:可以按Key排序。(数字、字母等)
注意:使用自定义类作为key时,类需要实现Comparable接口,String类作为key可以按key排序,因为String类本身已经实现了Comparable接口。
4、IdentityHashMap:key可以重复的Map集合
以上介绍的Map操作中key的值是不能重复的,例如,HashMap操作时如果key重复则肯定会覆盖之前的内容。
下面结合实例主要看一下Map集合输出全部内容以及IdentityHashMap的使用
这里的Key为一个自己定义的类Person2
class Person2 implements Serializable{
private static final long serialVersionUID = 1L;
private String name;
private int age;
public Person2(){}
public Person2(String name, int age){
this.name = name;
this.age = age;
}
// 重写equals,定义同一类型,并且属性name和age全部相等则实例对象相等
public boolean equals(Object obj){
if(this == obj){
return true;
}
if(!(obj instanceof Person2)){
return false;
}
Person2 p = (Person2) 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;//计算公式
}
// 重写toString打印自己想要的格式,如果不重写默认直接继承Object类的toString 方法是获取对象在内存中的值可能会乱码
public String toString(){
return "姓名:"+this.name+";年龄:"+this.age;
}
}
public class IdentityHashMapDemo {
/**
* key 可以重复的IdentityHashMap类
*/
public static void main(String[] args) {
Map<Person2,String> map = new IdentityHashMap<Person2,String>();
map.put(new Person2("张三",30), "张三1");
map.put(new Person2("张三",30), "张三2");//增加内容,key重复
map.put(new Person2("李四",31), "李四");
// 输出map集合全部内容:
// 声明Set集合(存单值),每个内容都是Map.Entry的对象,Map接口通过entrySet()变为set接口对象
Set<Map.Entry<Person2,String>> allSet = map.entrySet();
// 声明并实例化Iterator对象
Iterator<Map.Entry<Person2,String>> iter = allSet.iterator();
// 迭代输出
while(iter.hasNext()){
Map.Entry<Person2, String> m = iter.next();//每个对象都是Map.Entry实例
System.out.println(m.getKey()+"---->"+m.getValue());
}
}
}
输出结果:
姓名:张三;年龄:30---->张三1
姓名:李四;年龄:31---->李四
姓名:张三;年龄:30---->张三2
由此可见IdentityHashMap中key允许重复,只要两个对象的地址不相等即可。
5、Map接口使用需要注意的事项:
a、输出Map全部内容的方法,先转为Set接口对象,再利用Set对象实例化Iterator,利用Iterator输出每一个内容Map.Entry的对象
b、如果使用一个自定义的对象类表示Map中的key,则对象所在的类一定要重写equals()和HashCode()方法。