美文网首页
Map的遍历

Map的遍历

作者: Djbfifjd | 来源:发表于2021-01-15 22:44 被阅读0次

一、简述

Java 的 map 遍历有多种方法,如最早的 Iterator,Java5 支持的 foreach,Java8 的 Lambda。HashMap 遍历从大的方向可分为以下 4 类:

  1. 迭代器(Iterator)方式遍历;
  2. for each 方式遍历;
  3. Lambda 表达式遍历(JDK8+);
  4. Streams API 遍历(JDK8+)。

但每种类型下又有不同的实现方式,因此具体的遍历方式又可分为:

  1. 使用迭代器(Iterator)EntrySet 的方式进行遍历。
  2. 使用迭代器(Iterator)KeySet 的方式进行遍历。
  3. 使用 for each EntrySet 的方式进行遍历。
  4. 使用 for each KeySet 的方式进行遍历。
  5. 使用 Lambda 表达式的方式进行遍历。
public class TestMap {
  public static Map<String, String> map = new HashMap<String, String>();
    map.put("1", "大象");
    map.put("2", "猴子");
    map.put("3", "老虎");
}

二、entrySet

通过对 map entrySet 的遍历,可以同时拿到 key 和 value。这一般是最常见也是最可取的遍历方式,在键值都需要时使用。一般情况下,性能上要优于方法二。

// entrySet 获取key and value
public void testEntry() {
  for (Map.Entry<String, String> entry : map.entrySet()) {
     System.out.println(entry.getKey() + ":" + entry.getValue());
  }
}

三、keySet values

如果只需要 map 的 key 或者 value,用 map 的 keySet 或 values 方法无疑是最方便的,而不是用 entrySet。

Map<String, String> map = new HashMap<String, String>(); 
//遍历map中的键 
for (String key : map.keySet()) { 
  System.out.println("Key = " + key); 
} 
//遍历map中的值 
for (String value : map.values()) { 
  System.out.println("Value = " + value); 
}

如果需要同时获取 key 和 value,也可以先获取 key,然后再通过 map 的 get(key) 获取 value。作为方法一的替代,此代码更简洁,但实际上它相当慢且无效率。因为用键取值是耗时的操作(与方法一相比,在不同的 Map 实现中该方法慢了20%~200%)。该方法不是最优选择,一般不推荐使用。

// keySet get(key) 获取key and value
public void testKeySetAndGetKey() {
  for (String key : map.keySet()) {
    System.out.println(key + ":" + map.get(key));
  }
}

四、Iterator

对于上面的几种 foreach 都可以用 Iterator 代替,其实 foreach 在 Java5 中才被支持,foreach 的写法看起来更简洁。
但 Iterator 也有其优势:在用 foreach 遍历 map 时,如果改变其大小,会报错。但如果只是删除元素,可以使用 Iterator 的 remove 方法删除元素,根据 javadoc 的说明,如果在 foreach 遍历中尝试使用此方法,结果是不可预测的。

// Iterator entrySet 获取key and value
//Iterator:业务复杂的可以用while
public void testIterator() {
  Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();
  while (it.hasNext()) {
    Map.Entry<String, String> entry = it.next();
    System.out.println(entry.getKey() + ":" + entry.getValue());
    // it.remove(); 删除元素
  }
}
//Iterator:普通的可以用foreach遍历
for(Iterator<Map.Entry<String, String>> it = map.entrySet().iterator();it.hasNext();){
    Map.Entry<String,String> entry = it.next(); 
    System.out.println(entry.getKey() + ":" + entry.getValue());    
   //it.remove(); 会抛java.util.ConcurrentModificationException
}

五、Lambda~流式 map 遍历(Java8)

Java8 提供了 Lambda 表达式支持,语法更简洁,可以同时拿到 key 和 value。不过,经测试性能低于 entrySet,所以更推荐用 entrySet 的方式。

// Lambda 获取key and value
//流式一:
public void testLambda() {
   map.forEach((key, value) -> {
      System.out.println(key + ":" + value);
    });
}
//流式二:Streams API 单线程
map.entrySet().stream().forEach(entry->{
 System.out.println("code:"+entry.getKey()+" desc:"+entry.getValue());
});

//流式三:Streams API 多线程
map.entrySet().parallelStream().forEach((entry) -> {
  System.out.println(entry.getKey());
  System.out.println(entry.getValue());
});

六、小结

  1. 如果只是获取 key 或 value,推荐使用 keySet 或 values 方式。
  2. 如果同时需要 key 和 value 推荐使用 entrySet。
  3. 如果需要在遍历过程中删除元素推荐使用 Iterator。
  4. 如果需要在遍历过程中增加元素,可以新建一个临时 map 存放新增的元素,等遍历完毕,再把临时 map 放到原来的 map 中。

七、Java 中两个 map 比较

1️⃣用 map 的 keySet() 的迭代器(性能效率较低)

public void compareMap1() {
    Map<String, String> m1 = new HashMap<String, String>();//小
    Map<String, String> m2 = new HashMap<String, String>();//大
    Iterator<String> iter1 = m1.keySet().iterator();
    while (iter1.hasNext()) {
        String m1Key = iter1.next();
        //若两个map中相同key对应的value不相等
        if (!m1.get(m1Key).equals(m2.get(m1Key))) {
            //......
        }
    }
}

2️⃣用 map 的 entrySet() 的迭代器(性能效率较高)

public void compareMap2() {
    Map<String, String> m1 = new HashMap<String, String>();
    Map<String, String> m2 = new HashMap<String, String>();
    Iterator<Map.Entry<String, String>> iter1 = m1.entrySet().iterator();
    while (iter1.hasNext()) {
        Map.Entry<String, String> entry1 = iter1.next();
        String m1value = entry1.getValue() == null ? "" : entry1.getValue();
        String m2value = m2.get(entry1.getKey()) == null ? "" : m2.get(entry1.getKey());
        //若两个map中相同key对应的value不相等
        if (!m1value.equals(m2value)) {
            //其他操作...
        }
    }
}

3️⃣用 map 的 entrySet() 的增强型 for 循环(性能效率较高)

public void compareMap3() {
    Map<String, String> m1 = new HashMap<String, String>();
    Map<String, String> m2 = new HashMap<String, String>();
    for (Map.Entry<String, String> entry1 : m1.entrySet()) {
        String m1value = entry1.getValue() == null ? "" : entry1.getValue();
        String m2value = m2.get(entry1.getKey()) == null ? "" : m2.get(entry1.getKey());
        //若两个map中相同key对应的value不相等
        if (!m1value.equals(m2value)) {
            //其他操作...
        }
    }
}

相关文章

网友评论

      本文标题:Map的遍历

      本文链接:https://www.haomeiwen.com/subject/wmdgaktx.html