HashMap的几种遍历方式及循环删除

目录

  • 1. 前言
  • 2. `HashMap` 的遍历方式
    • 2.1. 迭代器 `EntrySet`
    • 2.2. 迭代器 `KeySet`
    • 2.3. `ForEach EntrySet`
    • 2.4. `ForEach KeySet`
    • 2.5. `Lambda` 表达式
    • 2.6. `Streams API`
  • 3. 循环删除
    • 3.1. 迭代器 `Iterator` 方式
    • 3.2. `ForEach` 循环方式
    • 3.3. `Lambda` 表达式
      • 3.3.1. `Lambda` 删除的正确方式
    • 3.4. `Stream` 方式
      • 3.4.1. `Stream` 循环的正确方式
    • 3.5. 小结

1. 前言

HashMap 遍历从大的方向来说,可分为以下 4

  • 迭代器 Iterator 方式遍历
  • ForEach 方式遍历
  • Lambda 表达式遍历
  • Streams API 遍历

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

  • 使用迭代器 Iterator EntrySet 的方式进行遍历
  • 使用迭代器 Iterator KeySet 的方式进行遍历
  • 使用 For Each EntrySet 的方式进行遍历
  • 使用 For Each KeySet 的方式进行遍历
  • 使用 Lambda 表达式的方式进行遍历
  • 使用 Streams API 的方式进行遍历

接下来我们来看每种遍历方式的具体实现代码

2. HashMap 的遍历方式

2.1. 迭代器 EntrySet

public class HashMapOneTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();        
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            System.out.println("Key的值为:" + entry.getKey());
            System.out.println("value的值为:" + entry.getValue());
        }
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第1张图片

2.2. 迭代器 KeySet

public class HashMapTwoTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        Iterator<Integer> iterator = hashMap.keySet().iterator();
        while (iterator.hasNext()) {
            Integer key = iterator.next();
            System.out.println("Key的值为:"+ key);
            System.out.println("value的值为:"+ hashMap.get(key));
        }
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第2张图片

2.3. ForEach EntrySet

public class HashMapThreeTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        for (Map.Entry<Integer, String> entry : hashMap.entrySet()) {
            System.out.println("Key的值为:" + entry.getKey());
            System.out.println("value的值为:" + entry.getValue());
        }
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第3张图片

2.4. ForEach KeySet

public class HashMapFourTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        for (Integer key : hashMap.keySet()) {
            System.out.println("Key的值为:" + key);
            System.out.println("Key的值为:" + hashMap.get(key));
        }
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第4张图片

2.5. Lambda 表达式

public class HashMapFiveTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        hashMap.forEach((key, value) -> {
            System.out.println("Key的值为:" + key);
            System.out.println("Value的值为:" + value);
        });
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第5张图片

2.6. Streams API

public class HashMapSixTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        hashMap.entrySet().stream().forEach((entry) -> {
            System.out.println("Key的值为:" + entry.getKey());
            System.out.println("value的值为:" + entry.getValue());
        });
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第6张图片

3. 循环删除

3.1. 迭代器 Iterator 方式

public class HashMapSevenTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        Iterator<Map.Entry<Integer, String>> iterator = hashMap.entrySet().iterator();
        while (iterator.hasNext()) {
            Map.Entry<Integer, String> entry = iterator.next();
            if (entry.getKey() == 1) {
                // 删除
                System.out.println("删除掉的Key为:" + entry.getKey());
                iterator.remove();
            } else {
                System.out.println("Map集合中剩余的Key为:" + entry.getKey());
            }
        }
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第7张图片
测试结果:在迭代器 Iterator 中循环删除数据是安全的

3.2. ForEach 循环方式

public class HashMapEightTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        for (Map.Entry<Integer, String> entry : hashMap.entrySet()) {
            if (entry.getKey() == 1) {
                // 删除
                System.out.println("删除掉的Key为:" + entry.getKey());
                hashMap.remove(entry.getKey());
            } else {
                System.out.println("Map集合中剩余的Key为:" + entry.getKey());
            }
        }
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第8张图片
测试结果:ForEach 循环中删除数据是不安全的,具体原因可以查看文章:为什么阿里巴巴禁止在foreach里进行集合(List、Map)元素的remove/add操作

3.3. Lambda 表达式

public class HashMapNineTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        hashMap.forEach((key, value) -> {
            if (key == 1) {
                // 删除
                System.out.println("删除掉的Key为:" + key);
                hashMap.remove(key);
            } else {
                System.out.println("Map集合中剩余的Key为:" + key);
            }
        });
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第9张图片
测试结果:Lambda 表达式循环中删除数据是不安全的

3.3.1. Lambda 删除的正确方式

public class HashMapNineTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        hashMap.keySet().removeIf(key -> key == 1);
        hashMap.forEach((key, value) -> {
            if (key == 1) {
                System.out.println("删除掉的Key为:" + key);
            } else {
                System.out.println("Map集合中剩余的Key为:" + key);
            }
        });
    }
}

3.4. Stream 方式

public class HashMapTenTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        hashMap.entrySet().stream().forEach((entry) -> {
            if (entry.getKey() == 1) {
                System.out.println("删除掉的Key为:" + entry.getKey());
                hashMap.remove(entry.getKey());
            } else {
                System.out.println("Map集合中剩余的Key为:" + entry.getKey());
            }
        });
    }
}

结果如下

HashMap的几种遍历方式及循环删除_第10张图片

测试结果:Stream 循环中删除数据是不安全的

3.4.1. Stream 循环的正确方式

public class HashMapTenTest {

    public static void main(String[] args) {
        Map<Integer, String> hashMap = new HashMap<>();
        hashMap.put(1, "Java");
        hashMap.put(2, "JDK");
        hashMap.put(3, "Spring Framework");
        hashMap.put(4, "MyBatis framework");
        hashMap.put(5, "Java中文社群");

        hashMap.entrySet().stream().filter(m -> 1 != m.getKey()).forEach((entry) -> {
            if (entry.getKey() == 1) {
                System.out.println("删除掉的Key为:" + entry.getKey());
                hashMap.remove(entry.getKey());
            } else {
                System.out.println("Map集合中剩余的Key为:" + entry.getKey());
            }
        });
    }
}

3.5. 小结

  • 不能在 ForEach 循环遍历中使用集合(List、Mapmap.remove() 来删除数据,这是非安全的操作方式
  • 可以使用迭代器 Iteratoriterator.remove() 的方法来删除数据,这是安全的删除集合的方式
  • 可以使用 Lambda 中的 removeIf 来提前删除数据,或者是使用 Stream 中的 filter 过滤掉要删除的数据进行循环,这样都是安全的

你可能感兴趣的:(java,#,集合,java)