0%

8.6 Java 8增强的Map集合

8.6 Java 8增强的Map集合

Map用于保存具有映射关系的数据,因此Map集合里保存着两组值,一组值用于保存Map里的key另外一组值用于保存Map里的value,keyvalue都可以是任何引用类型的数据。Mapkey不允许重复,即同一个Map对象的任何两个key通过equals()方法比较总是返回false
keyvalue之间存在单向一对一关系,即通过指定的key,总能找到唯一的、确定的value。从Map中取出数据时,只要给出指定的key,就可以取出对应的value。如果把Map的两组值拆开来看,Map里的数据有如图8.7所示的结构。
这里有一张图片
从图8.7中可以看出,如果把Map里的所有key放在一起来看,它们就组成了一个Set集合(所有的key没有顺序,keykey之间不能重复),实际上Map确实包含了一个keySet()方法,用于返回Map里所有key组成的Set集合。
不仅如此,Mapkey集和Set集合里元素的存储形式也很像,Map子类和Set子类在名字上也惊人地相似,比如Set接口下有HashSetLinkedHashSetSortedSet(接口)、 TreeSetEnumSet等子接口和实现类,而Map接口下则有HashMapLinkedHashMapSortedMap(接口)、 TreeMapEnumMap等子接口和实现类。正如它们的名字所暗示的,Map的这些实现类和子接口中key集的存储形式和对应Set集合中元素的存储形式完全相同。
提示
SetMap之间的关系非常密切。虽然Map中放的元素是key-value对,Set集合中放的元素是单个对象,但如果把key-value对中的value当成key的附庸:key在哪里, value就跟在哪里。这样就可以像对待Set一样来对待Map了。事实上,Map提供了一个Entry内部类来封装key-value对,而计算Entry存储时则只考虑Entry封装的key。从Java源码来看,Java是先实现了Map,然后通过包装一个所有value都为nullMap就实现了Set集合
如果把Map里的所有value放在一起来看,它们又非常类似于一个List:元素与元素之间可以重复每个元素可以根据索引来查找,只是Map中的索引不再使用整数值,而是以另一个对象作为索引。如果需要从List集合中取出元素,则需要提供该元素的数字索引;如果需要从Map中取出元素,则需要提供该元素的key索引。因此,Map有时也被称为字典,或关联数组

Map接口方法

Map接口中定义了如下常用方法。

方法 描述
Object put(Object key,Object value) 添加一个key-value对,如果当前Map中已有一个与该key相等的key-value对,则新的key-value对会覆盖原来的key-value对。
void putAll(Map map) 将指定Map中的key-value对复制到当前Map中。
Object get(Object key) 返回指定key所对应的value;如果此Map中不包含该key,则返回null
boolean isEmpty() 查询该Map是否为空(即不包含任何key-value对),如果为空则返回true
boolean containsKey(object key) 查询Map中是否包含指定的key,如果包含则返回true
Object remove(Object key) 删除指定key所对应的key-value对,返回被删除key所关联的value,如果该key不存在,则返回null
boolean remove(Object key,Object value) 这是Java8新增的方法,删除指定keyvalue所对应的key-value对。如果从该Map中成功地删除该key-value对,该方法返回true,否则返回false
int size() 返回该Map里的key-value对的个数。
void clear() 删除该Map对象中的所有key-value对.
Set keySet() 返回该Map中所有key组成的Set集合。
Collection values() 返回该Map里所有 value组成的 Collection
Set entrySet() 返回Map中包含的key-value对所组成的Set集合,每个集合元素都是 Map.Entry(EntryMap的内部类)对象。

Map的实现类

Map接口提供了大量的实现类,典型实现如HashMapHashtable等、 HashMap的子类LinkedHashMap,还有SortedMap子接口及该接口的实现类TreeMap,以及WeakHashMapIdentity HashMap等。下面将详细介绍Map接口实现类

Map的内部类Entry

Map中包括一个内部类Entry,该类封装了一个key-value对。 Entry包含如下三个方法。

方法 描述
Object getKey() 返回该Entry里包含的key值。
Object getValue() 返回该Entry里包含的value值。
Object setValue(V value) 设置该Entry里包含的value值,并返回新设置的value值。

Map集合最典型的用法就是成对地添加删除``key-value对,接下来即可判断该Map中是否包含指定key,是否包含指定value,也可以通过Map提供的keySet()方法获取所有key组成的集合,进而遍历Map中所有的key-value对。

实例

下面程序示范了Map的基本功能。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
import java.util.*;

public class MapTest
{
public static void main(String[] args)
{
Map map = new HashMap();
// 成对放入多个key-value对
map.put("疯狂Java讲义" , 109);
map.put("疯狂iOS讲义" , 10);
map.put("疯狂Ajax讲义" , 79);
// 多次放入的key-value对中value可以重复
map.put("轻量级Java EE企业应用实战" , 99);
// 放入重复的key时,新的value会覆盖原有的value
// 如果新的value覆盖了原有的value,该方法返回被覆盖的value
System.out.println(map.put("疯狂iOS讲义" , 99)); // 输出109
System.out.println(map); // 输出的Map集合包含4个key-value对
// 判断是否包含指定key
System.out.println("是否包含值为 疯狂iOS讲义 key:"
+ map.containsKey("疯狂iOS讲义")); // 输出true
// 判断是否包含指定value
System.out.println("是否包含值为 99 value:"
+ map.containsValue(99)); // 输出true
// 获取Map集合的所有key组成的集合,通过遍历key来实现遍历所有key-value对
for (Object key : map.keySet() )
{
// map.get(key)方法获取指定key对应的value
System.out.println(key + "-->" + map.get(key));
}
map.remove("疯狂Ajax讲义"); // 根据key来删除key-value对。
System.out.println(map); // 输出结果不再包含 疯狂Ajax讲义=79 的key-value对
}
}

运行结果:

1
2
3
4
5
6
7
8
9
10
{疯狂Ajax讲义=79, 疯狂iOS讲义=99, 轻量级Java EE企业应用实战=99, 疯狂Java讲义=109}
是否包含值为 疯狂iOS讲义 key:true
是否包含值为 99 value:true
疯狂Ajax讲义-->79
疯狂iOS讲义-->99
轻量级Java EE企业应用实战-->99
疯狂Java讲义-->109
{疯狂iOS讲义=99, 轻量级Java EE企业应用实战=99, 疯狂Java讲义=109}

上面程序中先示范了向Map中成对地添加key-value对。添加key-value对时,Map允许多个value重复,但如果添加key-value对时Map中已有重复的key,那么新添加的value会覆盖该key原来对应的value并返回被覆盖的value
程序接下来的代码分别判断了Map集合中是否包含指定key、指定value
程序中的foreach循环用于遍历Map集合:

  • 程序先调用Map集合的keySet()获取所有的key,然后使用foreach循环来遍历Map的所有key,根据key即可遍历所有的value.

所有的Map实现类都重写了toString()方法,调用Map对象的toString()方法总是返回如下格式的字符串:{key1=value,key2=value2…}.

原文链接: 8.6 Java 8增强的Map集合