java如何遍历map:四种主流实现
java如何遍历map是Java开发高频基础操作,主流实现包含entrySet迭代、keySet遍历、values单独取值、Java8Lambda流式遍历四类,适配HashMap、LinkedHashMap、TreeMap等Map接口实现类;如果你需要同时拿到key与value,优先选择entrySet方式,仅需要key时使用keySet,仅需要value集合时调用values(),JDK1.8及以上环境可使用forEachLambda简化代码。该操作存在明确边界:ConcurrentHashMap在遍历过程中,若使用普通迭代器执行put、remove结构性修改,会触发ConcurrentModificationException,这类并发Map需要使用迭代器自带的remove方法完成删除。
java如何遍历map:entrySet方式
你可以通过map.entrySet()获取Map.Entry集合,Map.Entry内部同时保存键和值,这是同时获取key、value时性能表现较好的写法,底层不需要二次通过key查询value,避免了keySet遍历之后再次get带来的额外哈希查找开销。基础迭代器写法代码如下:Iterator
entrySet也可以直接使用增强for循环,代码可读性更高,写法为for(Map.Entry
java如何遍历map:keySet与values方式
keySet()返回Map中所有key组成的Set集合,你可以遍历这个key集合,再通过map.get(key)拿到对应value。它适合只需要遍历全部key、不需要立刻读取value的场景,缺点是每一次get都要重新计算哈希、定位桶位,在大体积Map上整体耗时会高于entrySet。values()方法直接返回所有value的Collection视图,只需要读取全部值、不需要key的时候使用,不需要额外查询操作。
这里补充JDK官方规范,Map接口定义在java.util包下,自JDK1.2版本引入,entrySet、keySet、values都是Map接口声明的抽象方法,所有Map实现类都必须实现这三个方法。
java如何遍历map:Java8Lambda与Stream
JDK1.8为Map增加了default方法forEach,你可以直接调用map.forEach((k,v)->{System.out.println(k+"="+v);});,这是目前代码最简洁的写法,底层实现仍然是基于entrySet迭代,适合常规非并发Map,该写法内部没有暴露迭代器对象,循环体内不能安全删除元素。StreamAPI写法为map.entrySet().stream().forEach(entry->{...}),如果需要过滤、排序、收集结果,可以搭配filter、sorted等中间操作,适合需要对键值对做二次加工的业务场景。
| 遍历方式 | 能否同时获取key和value | 遍历中安全删除 | 适用JDK版本 |
|---|---|---|---|
| entrySet迭代器 | 是 | 支持it.remove() | JDK1.2+ |
| entrySet增强for | 是 | 不支持,直接remove会抛异常 | JDK1.5+ |
| keySet | 需要二次get | 迭代器版本支持remove | JDK1.2+ |
| Map.forEachLambda | 是 | 不支持 | JDK1.8+ |
TreeMap遍历会按照key的自然排序或者自定义Comparator顺序输出,LinkedHashMap会保留插入顺序,HashMap本身不保证迭代顺序,切换Map实现类之后,遍历输出顺序会发生变化,代码不能依赖遍历顺序做业务判断。
空Map不会抛出异常。
如果你处理的是ConcurrentHashMap,不要套用HashMap的快速失败逻辑,它的迭代器属于弱一致性迭代器,遍历期间允许并发更新,迭代结果不一定能反映遍历启动之后新增的数据,同时它也支持迭代器的remove操作,并发场景选型时要区分普通Map与并发Map的迭代语义差异。
