【Java集合框架】3 - 9 Map 双列集合顶级接口
§3-9 Map
双列集合顶级接口
目录
3-9.1 双列集合类体系结构
在正式开始学习 Map
双列集合前,先来看看双列集合的类结构:
同样地,这里双列集合也包含了用于并发编程的并发集合,这些集合在并发环境下是线程安全的,这些集合会在多线程与 JUC 并发编程中介绍。
3-9.2 双列集合常用的数据结构
Map
双列集合常用的数据结构如下图所示:
Map
体系的集合是双列集合,一次存储一对数据 <K,V>
,称为一个键值对(或键值对对象、Entry 对象)。
其中,K
为键(key),V
为值。键唯一,而值可能不唯一,且键与值一一对应。
Hashtable
及其子类 Properties
涉及与 IO 有关的方法,此处暂不考虑。
3-9.3 Map
接口
Map
是双列集合的父类接口,其功能可以由所有双列集合使用。
方法:
方法 | 描述 |
---|---|
V put(K key, V value) |
添加键值对 |
V remove(Object key) |
根据键删除指定键值对元素 |
void clear() |
清空当前集合 |
boolean containsKey(Object key) |
判断集合是否包含指定的键 |
boolean containsValue(Object value) |
判断集合是否包含指定的值 |
Set<K> keySet() |
返回该集合所有键构成的 Set 集合 |
Collection<V> values() |
返回该集合所有值构成的 Collection 集合 |
V get(Object key) |
返回指定键所映射的值 |
boolean isEmpty() |
判断集合是否为空 |
int size() |
返回集合的长度,即集合中键值对个数 |
注意:
put
方法具有覆盖功能,该方法会将指定键所对应的值用新值覆盖,并返回旧值;get
方法若找不到对应地的值,则返回null
;- 创建
Map
的实现类对象时,注意应当传入两个泛型参数;
3-9.4 遍历方式
Map
内元素有多种不同的遍历方式。
3-9.4.1 键找值
将 Map
中所有的键抽取出来,并存放到一个单列集合中。再遍历该单列集合,对每个元素使用 get
方法获取对应值。
在单列集合中,则可以使用 Collection
的三种遍历方式,示例:
//遍历方式
//键找值:获取键的Set集合,用 get 获取值
Set<String> keys = map.keySet();
//迭代器
Iterator<String> it = keys.iterator();
while (it.hasNext()) {
String key = it.next();
System.out.println(key + "=" + map.get(key));
}
System.out.println("==============");
//增强 for
for (String key : keys) {
System.out.println(key + "=" + map.get(key));
}
System.out.println("==============");
//forEach
keys.forEach(key -> {
System.out.println(key + "=" + map.get(key));
});
System.out.println("==============");
3-9.4.2 键值对
将 Map
中的键值对直接打包成一个 Set
集合返回。再遍历该单列集合,通过 getKey
和 getValue
方法获取键和值。
Entry<K,V>
是 Map
中的一个内部接口,可直接通过 Map.Entry<K,V>
访问。
示例:
//键值对
Set<Map.Entry<String, String>> entries = map.entrySet();
//迭代器
Iterator<Map.Entry<String, String>> it2 = entries.iterator();
while (it2.hasNext()) {
Map.Entry<String, String> next = it2.next();
System.out.println(next.getKey() + "=" + next.getValue());
}
System.out.println("==============");
//增强 for
for (Map.Entry<String, String> entry : entries) {
System.out.println(entry.getKey() + "=" + entry.getValue());
}
System.out.println("==============");
//forEach
entries.forEach(entry -> {
System.out.println(entry.getKey() + "=" + entry.getValue());
});
System.out.println("==============");
3-9.4.3 Lambda 表达式
JDK 8 引入了 Lambda 表达式,提供了一种更简单、更直接的遍历方式。
方法 | 描述 |
---|---|
default void forEach(BiConsumer<? super K, ? super V> action) |
结合 Lambda 表达式遍历集合 |
该方法位于 Map
接口中,其中,BiConsumer<T,U>
是一个位于 java.util.function
的函数式接口,其内部含有一个抽象方法 accepct
,用于执行接收两个参数但无返回值的操作,类似于 Consumer
中的 accepct
方法,可用 Lambda 表达式简化。
forEach
默认方法体:
default void forEach(BiConsumer<? super K, ? super V> action) {
Objects.requireNonNull(action);
for (Map.Entry<K, V> entry : entrySet()) {
K k;
V v;
try {
k = entry.getKey();
v = entry.getValue();
} catch (IllegalStateException ise) {
// this usually means the entry is no longer in the map.
throw new ConcurrentModificationException(ise);
}
action.accept(k, v);
}
}
示例:
//forEach:匿名内部类
map.forEach(new BiConsumer<String, String>() {
@Override
public void accept(String key, String value) {
System.out.println(key + "=" + value);
}
});
System.out.println("==============");
//forEach:Lambda
map.forEach((key, value) -> System.out.println(key + "=" + value));
System.out.println("==============");