目录
- 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());}}
}
结果如下
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));}}
}
结果如下
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());}}
}
结果如下
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));}}
}
结果如下
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);});}
}
结果如下
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());});}
}
结果如下
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());}}}
}
结果如下
测试结果:在迭代器 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());}}}
}
结果如下
测试结果:在 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);}});}
}
结果如下
测试结果:在 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());}});}
}
结果如下
测试结果:在 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、Map
)map.remove()
来删除数据,这是非安全的操作方式 - 可以使用迭代器
Iterator
的iterator.remove()
的方法来删除数据,这是安全的删除集合的方式 - 可以使用
Lambda
中的removeIf
来提前删除数据,或者是使用Stream
中的filter
过滤掉要删除的数据进行循环,这样都是安全的