偶对象保存:Map接口
我们前面讲到的Collection属于单值保存父接口,每次只能保存一个对象;而我们这节讲的Map属于偶对象保存接口,利用Map可以保存一对关联数据(按照"key = value"的形式)。
Map接口的常用方法
No | 方法名称 | 类型 | 描述 |
---|---|---|---|
1 | public V put(K key,V value) | 普通 | 向集合中保存对象 |
2 | public V get(Object key) | 普通 | 根据key查找对应的value数据 |
3 | public Set<Map.Entry<K,V>>entrySet() | 普通 | 将Map集合转化为Set集合 |
4 | public Set< K >keySet() | 普通 | 取出全部的key |
Map接口中两个常用的子类:HashMap、Hashtable。
HashMap
例:观察HashMap子类的基本使用
package Project.Study.Map.HashMap;
import java.util.HashMap;
import java.util.Map;
public class Test1 {
public static void main(String[]args){
Map<String,Integer>map = new HashMap<>(); //定义Map集合
map.put("One",1); //保存数据
map.put("一",1);
map.put("一",2); //key数据重复
map.put("一一",11);
map.put(null,0); //key为null
map.put("空",null); //value数据为null
System.out.println(map); //输出全部map集合
}
}
//结果:
//{一=2, null=0, One=1, 一一=11, 空=null}
由上程序我们可以发现Map集合有如下特点:
- 使用HashMap定义的Map集合是无序存放的(顺序无用);
- 如果发现了重复的key会进行覆盖,使用新的key内容来替换旧的内容;
- 使用HashMap子类保存数据时key或value可以保存为null。
例:查询操作
package Project.Study.Map.HashMap;
import java.util.HashMap;
import java.util.Map;
public class Test2 {
public static void main(String[]args){
Map<String,Integer>map = new HashMap<>(); //定义Map集合
map.put("高数成绩",89); //保存数据
map.put("英语成绩",78);
map.put("离散成绩",96);
System.out.println(map.get("高数成绩")); //key存在则返回value
System.out.println(map.get("离散成绩"));
System.out.println(map.get("英语成绩"));
System.out.println(map.get("线代成绩")); //key不存在则返回null
}
}
//结果:
//89
//96
//78
//null
由此我们可以发现Map和Colletion的区别,Map接口保存数据主要是为了通过key来进行查询,而Collection接口保存数据的目的则是输出。
Hashtable
Hashtable使用的注意事项:
在使用Hashtable子类实例化的Map集合中,保存的key或value都不允许出现null,否则会出现异常。
例:使用Hashtable
package Project.Study.Map.Hashtable;
import java.util.Hashtable;
import java.util.Map;
public class Test1 {
public static void main(String[]args){
Map<String,Integer>map = new Hashtable<>(); //定义Map集合
map.put("高数",100);
map.put("离散",99);
map.put("高数",88);
map.put("离散",92);
System.out.println(map.get("高数")); //key存在返回value
System.out.println(map.get("离散"));
System.out.println(map.get("英语")); //key不存在返回null
}
}
//结果:
//88
//92
//null
HashMap与Hashtable的区别
No. | 区别点 | HashMap | Hashtable |
---|---|---|---|
1 | 推出时间 | JDK 1.2推出 | JDK 1.0推出 |
2 | 性能 | 采取异步处理 | 采取同步处理 |
3 | 数据安全 | 非线程安全 | 线程安全 |
4 | 设置null | 允许key或value内容为null | 不允许key或value的内容设置为null |
利用Iterator输出Map集合
当使用Map集合保存数据时,所保存的key与value会自动包装为Map.Entry接口对象,也就是说如果利用Iterator进行迭代,那么每当使用next()方法读取数据时返回的都是一个Map.Entry接口对象,此接口定义如下:
public static interface Map.Entry<K,V>{}
通过定义我们可以发现Map.Entry接口属于Map接口定义的一个static内部接口(相当于外部接口)。Map.Entry接口定义的常用方法如下:
No. | 方法 | 类型 | 描述 |
---|---|---|---|
1 | public K getKey() | 普通 | 取得数据中的key |
2 | public V getValue() | 普通 | 取得数据中的value |
3 | public V setValue(V value) | 普通 | 修改数据中的value |
在Map接口中定义了一个entrySet()方法,而实现Iterator输出Map集合的关键就在于此方法的使用上,步骤如下:
- 利用entrySet()方法将Map接口数据中的数据转换为Set接口实例化进行保存,此时Set接口中所使用的泛型类型为Map.Entry,而Map.Entry中的K与V的泛型类型则与Map集合定义的K与V类型相同;
- 利用Set接口中的iterator()方法将集合Set转化为Iterator接口实例;
- 利用Iterator接口进行迭代输出,每一次迭代取得的都是Map.Entry接口实例,利用此接口实例可以进行key与value的分离。
例:利用Iterator实现Map接口的输出
package Project.Study.Map;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
public class Test1 {
public static void main(String[]args){
Map<String,Integer>map = new Hashtable<>(); //定义Map集合
map.put("高数",98); //保存数据
map.put("离散",78);
map.put("英语",87);
map.put("英语",81); //key数据重复
//将Map集合变为Set集合,目的是使用iterator()方法,注意泛型的统一
Set<Map.Entry<String,Integer>>set = map.entrySet();
Iterator<Map.Entry<String,Integer>>iter = set.iterator();//取得Iterator实例
while(iter.hasNext()){ //迭代输出
Map.Entry<String,Integer>ma = iter.next(); //取出Map.Entry
System.out.println(ma.getKey()+"="+ma.getValue()); //输出数据
}
}
}
//结果:
//英语=81
//离散=78
//高数=98
自定义Map集合的key类型
我们可以使用自定义的类型作为key,而作为key自定义的类必须覆写Object类中的hashCode()与equals()两个方法,因为只有靠这两个方法才能确定元素是否重复。
例:使用自己定义的类作为Map集合的key
package Project.Study.Map;
import java.util.HashMap;
import java.util.Map;
class Student{ //此类为要保存的key类型
private String name; //只定义一个属性
public Student(String name){ //构造方法接收数据
this.name = name;
}
@Override
public String toString(){
return "学生姓名:"+this.name;
}
@Override
public int hashCode(){ //取得对象编码
final int prime = 31;
int result = 1;
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 (name==null){
if (other.name!=null){
return false;
}else if (!name.equals(other.name)){
return false;
}
}
return true;
}
}
public class Test2 {
public static void main(String[]args){
Map<Student,Integer>map = new HashMap<>(); //实例化Map接口集合
map.put(new Student("小泓"),100); //向Map接口保存数据
System.out.println(map.get(new Student("小泓"))); //根据key取得value
}
}
//结果:
//100