Map 接口不是 Collection 接口的继承. 而是从自己的用于维护键 - 值关联的接口层次结构入手. 按定义, 该接口描述了从不重复的键到值的映射.
我们可以把这个接口方法分成三组操作: 改变, 查询和提供可选视图.
改变操作允许您从映射中添加和除去键 - 值对. 键和值都可以为 null. 但是, 您不能把 Map 作为一个键或值添加给自身.
Object put(Object key,Object value): 用来存放一个键 - 值对 Map 中
Object remove(Object key): 根据 key(键), 移除一个键 - 值对, 并将值返回
voidputAll(Map mapping) : 将另外一个 Map 中的元素存入当前的 Map 中
void clear() : 清空当前 Map 中的元素
查询操作允许您检查映射内容:
Object get(Object key) : 根据 key(键) 取得对应的值
boolean containsKey(Object key) : 判断 Map 中是否存在某键 (key)
boolean containsValue(Object value): 判断 Map 中是否存在某值 (value)
int size(): 返回 Map 中键 - 值对的个数
boolean isEmpty() : 判断当前 Map 是否为空
publicSet keySet() : 返回所有的键 (key), 并使用 Set 容器存放
public Collection values() : 返回所有的值 (Value), 并使用 Collection 存放
publicSet entrySet() : 返回一个实现 Map.Entry 接口的元素 Set
因为映射中键的集合必须是唯一的, 就使用 Set 来支持. 因为映射中值的集合可能不唯一, 就使用 Collection 来支持. 最后一个方法返回一个实现 Map.Entry 接口的元素 Set.
我们看看 Map 的常用实现类的比较, 如下表:
简述 | 实现 | 操作特性 | 成员要求 | |
Map | 保存键值对成员,基于键找值操作,使用 compareTo 或 compare 方法对键进行排序 | HashMap | 能满足用户对 Map 的通用需求 | 键成员可为任意 Object 子类的对象,但如果覆盖了 equals 方法,同时注意修改 hashCode 方法。 |
TreeMap | 支持对键有序地遍历,使用时建议先用 HashMap 增加和删除成员,最后从 HashMap 生成 TreeMap;附加实现了 SortedMap 接口,支持子 Map 等要求顺序的操作 | 键成员要求实现 Comparable 接口,或者使用 Comparator 构造 TreeMap 键成员一般为同一类型。 | ||
LinkedHashMap | 保留键的插入顺序,用 equals 方法检查键和值的相等性 | 成员可为任意 Object 子类的对象,但如果覆盖了 equals 方法,同时注意修改 hashCode 方法。 |
- import java.util.*;
- publicclass MapTest {
- publicstaticvoid main(String[] args) {
- Map map1 = new HashMap();
- Map map2 = new HashMap();
- map1.put("1","aaa1");
- map1.put("2","bbb2");
- map2.put("10","aaaa10");
- map2.put("11","bbbb11");
- // 根据键 "1" 取得值:"aaa1"
- System.out.println("map1.get(\"1\")="+map1.get("1"));
- // 根据键 "1" 移除键值对 "1"-"aaa1"
- System.out.println("map1.remove(\"1\")="+map1.remove("1"));
- System.out.println("map1.get(\"1\")="+map1.get("1"));
- map1.putAll(map2);// 将 map2 全部元素放入 map1 中
- map2.clear();// 清空 map2
- System.out.println("map1 IsEmpty?="+map1.isEmpty());
- System.out.println("map2 IsEmpty?="+map2.isEmpty());
- System.out.println("map1 中的键值对的个数 size ="+map1.size());
- System.out.println("KeySet="+map1.keySet());//set
- System.out.println("values="+map1.values());//Collection
- System.out.println("entrySet="+map1.entrySet());
- System.out.println("map1 是否包含键: 11 ="+map1.containsKey("11"));
- System.out.println("map1 是否包含值: aaa1 ="+map1.containsValue("aaa1"));
- }
- }
运行输出结果为:
- map1.get("1")=aaa1
- map1.remove("1")=aaa1
- map1.get("1")=null
- map1 IsEmpty?=false
- map2 IsEmpty?=true
map1 中的键值对的个数 size = 3
- KeySet=[10, 2, 11]
- values=[aaaa10, bbb2, bbbb11]
- entrySet=[10=aaaa10, 2=bbb2, 11=bbbb11]
map1 是否包含键: 11 = true
map1 是否包含值: aaa1 = false
在该例子中, 我们创建一个 HashMap, 并使用了一下 Map 接口中的各个方法.
其中 Map 中的 entrySet() 方法先提一下, 该方法返回一个实现 Map.Entry 接口的对象集合. 集合中每个对象都是底层 Map 中一个特定的键 - 值对.
Map.Entry 接口是 Map 接口中的一个内部接口, 该内部接口的实现类存放的是键值对. 在下面的实现原理中, 我们会对这方面再作介绍, 现在我们先不管这个它的具体实现.
我们再看看排序的 Map 是如何使用:
- import java.util.*;
- publicclass MapSortExample {
- publicstaticvoid main(String args[]) {
- Map map1 = new HashMap();
- Map map2 = new LinkedHashMap();
- for(int i=0;i<10;i++){
- double s=Math.random()*100;// 产生一个随机数, 并将其放入 Map 中
- map1.put(new Integer((int) s),"第"+i+"个放入的元素:"+s+"\n");
- map2.put(new Integer((int) s),"第"+i+"个放入的元素:"+s+"\n");
- }
- System.out.println("未排序前 HashMap:"+map1);
- System.out.println("未排序前 LinkedHashMap:"+map2);
- // 使用 TreeMap 来对另外的 Map 进行重构和排序
- Map sortedMap = new TreeMap(map1);
- System.out.println("排序后:"+sortedMap);
- System.out.println("排序后:"+new TreeMap(map2));
- }
- }
该程序的一次运行结果为:
未排序前 HashMap:{64 = 第 1 个放入的元素: 64.05341725531845
, 15 = 第 9 个放入的元素: 15.249165766266382
, 2 = 第 4 个放入的元素: 2.66794706854534
, 77 = 第 0 个放入的元素: 77.28814965781416
, 97 = 第 5 个放入的元素: 97.32893518378948
, 99 = 第 2 个放入的元素: 99.99412014935982
, 60 = 第 8 个放入的元素: 60.91451419025399
, 6 = 第 3 个放入的元素: 6.286974058646977
, 1 = 第 7 个放入的元素: 1.8261658496439903
, 48 = 第 6 个放入的元素: 48.736039522423106
}
未排序前 LinkedHashMap:{77 = 第 0 个放入的元素: 77.28814965781416
, 64 = 第 1 个放入的元素: 64.05341725531845
, 99 = 第 2 个放入的元素: 99.99412014935982
, 6 = 第 3 个放入的元素: 6.286974058646977
, 2 = 第 4 个放入的元素: 2.66794706854534
, 97 = 第 5 个放入的元素: 97.32893518378948
, 48 = 第 6 个放入的元素: 48.736039522423106
, 1 = 第 7 个放入的元素: 1.8261658496439903
, 60 = 第 8 个放入的元素: 60.91451419025399
, 15 = 第 9 个放入的元素: 15.249165766266382
}
排序后:{1 = 第 7 个放入的元素: 1.8261658496439903
, 2 = 第 4 个放入的元素: 2.66794706854534
, 6 = 第 3 个放入的元素: 6.286974058646977
, 15 = 第 9 个放入的元素: 15.249165766266382
, 48 = 第 6 个放入的元素: 48.736039522423106
, 60 = 第 8 个放入的元素: 60.91451419025399
, 64 = 第 1 个放入的元素: 64.05341725531845
, 77 = 第 0 个放入的元素: 77.28814965781416
, 97 = 第 5 个放入的元素: 97.32893518378948
, 99 = 第 2 个放入的元素: 99.99412014935982
}
排序后:{1 = 第 7 个放入的元素: 1.8261658496439903
, 2 = 第 4 个放入的元素: 2.66794706854534
, 6 = 第 3 个放入的元素: 6.286974058646977
, 15 = 第 9 个放入的元素: 15.249165766266382
, 48 = 第 6 个放入的元素: 48.736039522423106
, 60 = 第 8 个放入的元素: 60.91451419025399
, 64 = 第 1 个放入的元素: 64.05341725531845
, 77 = 第 0 个放入的元素: 77.28814965781416
, 97 = 第 5 个放入的元素: 97.32893518378948
, 99 = 第 2 个放入的元素: 99.99412014935982
}
从运行结果, 我们可以看出, HashMap 的存入顺序和输出顺序无关. 而 LinkedHashMap 则保留了键值对的存入顺序. TreeMap 则是对 Map 中的元素进行排序. 在实际的使用中我们也经常这样做: 使用 HashMap 或者 LinkedHashMap 来存放元素, 当所有的元素都存放完成后, 如果使用则是需要一个经过排序的 Map 的话, 我们再使用 TreeMap 来重构原来的 Map 对象. 这样做的好处是: 因为 HashMap 和 LinkedHashMap 存储数据的速度比直接使用 TreeMap 要快, 存取效率要高. 当完成了所有的元素的存放后, 我们再对整个的 Map 中的元素进行排序. 这样可以提高整个程序的运行的效率, 缩短执行时间.
这里需要注意的是, TreeMap 中是根据键 (Key) 进行排序的. 而如果我们要使用 TreeMap 来进行正常的排序的话, Key 中存放的对象必须实现 Comparable 接口.
来源: http://www.bubuko.com/infodetail-3136001.html