Collection、Set、List 接口都属于单值的操作,即每次只能操作一个对象,而 Map 与每次操作的是一对对像,即二元偶对象,Map 中的每个元素都使用 key->value 的形式存储在集合中。
Map 接口的定义:
public interface Map<K,V>
在 Map 上也应用了泛型,必须同时设置好 key 或 value 的类型,在 Map 中每一对
key -> value都表示一个值。Map 接口中方法:
Map.Entry 是 Map 内部定义的一个接口,专门用来保存 key->value 的内容。定义如下:
public static interface Map.Entry<K,V>
Map.Entry
是使用 static 关键字声明的内部接口,此接口可以由外部通过“外部类.内部类
”的形式直接调用。
Map.Entry
接口的常用方法:
在 Map 操作中,所有的内容都是通过 key->value 的形式保存数据,对于集合来讲实际上是将 key->value
的数据保存在 Map.Entry
的实例之后,再在 Map 集合中插入的是一个 Map.Entry
的实例化对象:
Map.Entry
在集合输出时会使用到
如果要想使用 Map 接口也必须依靠其子类实例化,Map接口中常用的子类:
HashMap:无序存放,是新的操作类,key 不允许重复
Hashtable:无序存放,是旧的操作类,key 不允许重复
TreeMap:可以排序的 Map 集合,按集合中的 key 排序,key 不允许重复
WeakHashMap:弱引用的 Map 集合,当集合中的某些内容不再使用时清除掉无用的数据,使用 gc 进行回收
IdentifyHashMap:key 可以重复的 Map 集合
HashMap 本身是 Map 的子类,直接使用此类为 Map 接口实例化即可
在 Map 接口中可以使用 put(Object key,Object value) 方法向集合中增加内容,之后可以使用 get(E key) 方法根据 key 找出其对应的 value。
public class Root{
public static void main(String[] args) {
Map<String,String > map = new HashMap<String, String>();//实例化 map
map.put("1","Java");
map.put("2","Python");
String val = map.get("2");//根据 key 求出 value
System.out.println("取出的内容是:" + val);
}
}
如果要判断某一个指定的额 key 或 value 是否存在,可以使用 Map 接口中提供的 containsKey(Object key) 和 containsValue(Object value) 两个方法,前者判断Map集合是否存在指定的 key,后者判断 Map 集合是否存在指定的 value
public class Root{
public static void main(String[] args) {
Map<String,String > map = new HashMap<String, String>();//实例化 map
map.put("1","Java");
map.put("2","Python");
if (map.containsKey("1")) {
System.out.println("搜索的 key 存在!");
}
if (map.containsValue("Python")) {
System.out.println("搜索的 Value 存在!");
}
}
}
在 Map 中提供了一个叫做 keySet() 的方法,可以将一个 Map 中的全部 key 变为一个 Set 集合,一旦有了 Set 实例,就可以直接使用 Iterator 输出。但是在进行操作时一定要注意接收的 Set 集合中指定的泛型要和 Map 中的key的泛型类型保持一致
public class Root{
public static void main(String[] args) {
Map<String,String > map = new HashMap<String, String>();//实例化 map
map.put("1","Java");
map.put("2","Python");
Set<String > keys = map.keySet();//得到全部的 key
Iterator<String> iter = keys.iterator();
System.out.print("全部的 key:");
while (iter.hasNext()){
String str = iter.next();
System.out.print(str + "、");
}
}
}
如果要输出全部的 value,则使用 values() 方法,此方法的返回类型是 Collection,在进行操作时也同样需要注意泛型的类型
public class Root{
public static void main(String[] args) {
Map<String,String > map = new HashMap<String, String>();//实例化 map
map.put("1","Java");
map.put("2","Python");
Collection<String > values = map.values();//得到全部的 key
Iterator<String> iter = values.iterator();
System.out.print("全部的 value:");
while (iter.hasNext()){
String str = iter.next();
System.out.print(str + "、");
}
}
}
TreeMap 的主要功能是按 key 排序
import java.util.*;
public class Root{
public static void main(String[] args) {
Map<String,String > map = new TreeMap<String, String>();//实例化 map
map.put("2","Java");
map.put("1","Python");
map.put("3","Html");
Set<String > keys = map.keySet();//得到全部的 key
Iterator<String> iter = keys.iterator();
while (iter.hasNext()){
String str = iter.next();
System.out.println(str + " --> " + map.get(str));//取出 key 对应的内容
}
}
}
这里需要注意使用自定义类作为 key 类需要实现 Comparable 接口
因为程序中国使用的是String作为 key ,因为String 本身已经实现了 Comparable 接口,所以可以直接执行,而如果使用一个自定义的类作为 key,则此类必须实现 Comparable 接口,否则将出现类转换异常。
无论是 HashMap 还是TreeMap 都是使用强引用保存的,即里面的内容不管是否使用都始终在集合中保留,如果希望集合自动清理暂时不用的数据就使用 WeakHashMap类。这样当进行垃圾收集时会释放掉集合中的垃圾信息
WeakHashMap 的定义:
public class WeakHashMap<K,V> extends AbstractMap<K,V>
implements Map<K,V>
public class Test{
public static void main(String[] args) {
Map<String,String > map = new WeakHashMap<String, String>();//实例化 map
map.put("2","Java");
map.put(new String("1"),new String("Python"));
System.gc();//进行垃圾收集
map.put("3","Html");
System.out.println("内容:" + map);
}
}
可以看出使用 map.put()
的方式不同,会达到不同的强引用和弱引用效果
对于 Map 接口来说,其本身是不能直接使用迭代(Iterator、foreach)进行输出的,因为 Map 中的每个位置存放的是一对值(key->value),而 Iterator 中每次只能找到一个值
所以,如果非要使用迭代进行输出,必须按照以下步骤(以 Iterator 输出方法为例):
(1)将 Map 的实例通过 entrySet() 方法变为 Set 接口
(2)通过 Set 接口实例为 Iterator 实例化
(3)通过 Iterator 迭代输出,每个内容都是 Map.Entry
的对象
(4)通过 Map.Entry
进行 key->value 的分离
Map 一般很少直接输出,只是作为查询使用,而 Collection 接口在开发中主要作用是传递内容及输出。
public class Test{
public static void main(String[] args) {
Map<String,String > map = new HashMap<String, String>();//实例化 map
map.put("2","Java");
map.put("1","Python");
map.put("3","Html");
Set<Map.Entry<String ,String >> allSet = null;//声明一个 Set 集合,指定泛型
allSet = map.entrySet();//将 Map 接口实例变为 Set 接口实例
Iterator<Map.Entry<String ,String >> iter = null;//声明 Iterator 对象
iter = allSet.iterator();//实例化 Iterator 对象
while (iter.hasNext()){
Map.Entry<String ,String > me = iter.next();//找到 Map.Entry 实例
System.out.println(me.getKey() + "-->" + me.getValue());//输出 key 和 value
}
}
}
public class Test{
public static void main(String[] args) {
Map<String,String > map = new HashMap<String, String>();//实例化 map
map.put("2","Java");
map.put("1","Python");
map.put("3","Html");
for (Map.Entry<String ,String> me:map.entrySet()){//输出 Set 集合
System.out.println(me.getKey() + "-->" + me.getValue());
}
}
}
如果使用一个自定义的对象表示 Map 中的 key,则对象所在的类中一定要覆写 equals() 和 hashCode() 方法,否则无法找到对应的 value
import java.util.HashMap;
import java.util.Map;
class Person{
private String name;
private int age;
public Person(String name,int age){
this.name = name;
this.age = age;
}
public boolean equals(Object obj){//覆写 equals() 方法
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;
}
}
public int hashCode(){//覆写 hashCode() 方法
return this.name.hashCode() * this.age;//计算公式
}
public String toString(){
return "姓名" + this.name + ";年龄:" + this.age;//返回信息
}
}
public class Test{
public static void main(String[] args) {
Map<Person,String> map = null;
map = new HashMap<Person,String >();//实例化 Map 对象
Person per = new Person("Java",30);
map.put(per,"Python");
System.out.println(map.get(per));
}
}
前面所述的 Map 操作中 key 的值是不能重复的,如果重复会覆盖之前的内容,此时可以使用 IdentityHashMap,使用此类只有地址不相等(key1 != key2),就表示不是重复的 key,可以添加到集合中。
public class Test{
public static void main(String[] args) {
Map<Person,String> map = new IdentityHashMap<Person,String >();
map.put(new Person("张三",30),"J1");
map.put(new Person("李四",31),"J2");
map.put(new Person("李四",31),"J3");
map.put(new Person("王二",32),"J4");
Set<Map.Entry<Person,String >> allSet = null;//声明一个 Set 集合
allSet = map.entrySet();//将 Map 接口实例为 Set 接口实例
Iterator<Map.Entry<Person,String >> iter = null;
iter = allSet.iterator();//实例化 Iterator 对象
while (iter.hasNext()){
Map.Entry<Person,String > me = iter.next();//每个对象都是 Map.Entry 实例
System.out.println(me.getKey() + "-->" + me.getValue());//输出 key 和 value
}
}
}