Map 是我们在开发中常用的数据结构,它采用了键值对的数据存储方式,很适合用来缓存数据。

假设这么一个场景:我需要对缓存到 Map 中的数据做网络传输,或者本地持久化操作,应该怎么操作?

最粗暴的方法就是逐个读写,比如:

public void postData(Map<String, Object> map) {
    Object value1 = map.get("key_1");
    Object value2 = map.get("key_2");
    ...
    JSONObject json = new JSONObject();
    json.put("key_1", value1);
    json.put("key_2", value2);
    ...
}

Map 中的数据非常多时,逐个读写的方式会显得格外臃肿。

在这种场景下,我们大概率不关心各个键值对的数据内容,其实可以直接采用遍历的方法。

Map 的遍历有多种实现方式:

Map.keySet()

public static void mapTraversal(Map<Object, Object> map) {
    for (Object key : map.keySet()) {
        Object value = map.get(key);
        // Do something...
    }
}

利用 foreach 循环,通过 MapkeySet() 遍历得出所有的 key,再利用 key 取得 value

MapkeySet() 方法返回的是一个包含该 Map 中所有 keySet 集合,因为 Set 具备迭代器,所以能够遍历取出对应的值。

Map.entrySet()

public void mapTraversal(Map<Object, Object> map) {
    for (Map.Entry<Object, Object> entry : map.entrySet()) {
        Object key = entry.getKey();
        Object value = entry.getValue();
        // Do something...
    }
}

Map 中采用 Entry 内部类来表示一个映射项,映射项包含了 keyvalue,而 MapentrySet() 方法返回的就是一个包含此映射项的 Set 集合,所以我们可以直接对其遍历。

Iterator

public static void mapTraversal(Map<Object, Object> map) {
    Iterator<Map.Entry<Object, Object>> it = map.entrySet().iterator();
    while (it.hasNext()) {
        Map.Entry<Object, Object> entry = it.next();
        Object key = entry.getKey();
        Object value = entry.getValue();
        // Do something...
    }
}

IteratorMap 的遍历依然是使用 MapentrySet() 方法取映射,套上 Iterator 似乎有点多此一举,但当你需要从 Map 中移除元素时,foreach 便无能为力了,而 Iteratorremove() 方法则能够帮你轻松实现。

Java 8 forEach() Lambda

public static void mapTraversal(Map<Object, Object> map) {
    map.forEach((key, value) -> {
        // Do something...
    });
}

Java 8 提供了 Lambda 表达式支持,而 Map 也在 Java 8 加入了 forEach() 方法,语法看起来更简洁,可以同时拿到 keyvalue

同时,由于 Collection 本身就继承自 Iterable,因此 keySet()entrySet() 所获取到的 Set 集合便支持 IterableforEach() 方法。