参考链接:
java 中 List 的5种遍历方式
Java 中 Set 的4中遍历方式
Java 中 Map 的5种遍历方式
在 Java 中遍历 HashMap 的5种最佳方式
2020-03-14 10:41·骇客与画家
原文地址:
https://www.javaguides.net/2020/03/5-best-ways-to-iterate-over-hashmap-in-java.html[1]作者:Ramesh Fadatare[2]
翻译:高行行
在本文中,我们将通过示例讨论在 Java 上遍历 HashMap[3] 的五种最佳方法。
- 使用 Iterator 遍历 HashMap EntrySet
- 使用 Iterator 遍历 HashMap KeySet
- 使用 For-each 循环迭代 HashMap
- 使用 Lambda 表达式[4]遍历 HashMap
- 使用 Stream API[5] 遍历 HashMap
通过
https://www.javaguides.net/2018/07/java-8-lambda-expressions.html [6]了解有关 lambda 表达式的信息
1. 使用 Iterator 遍历 HashMap EntrySet
package com.java.tutorials.iterations;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Map.Entry;
/**
* 在 Java 中遍历 HashMap 的5种最佳方法
* @author Ramesh Fadatare
*
*/
public class IterateHashMapExample {
public static void main(String[] args) {
// 1. 使用 Iterator 遍历 HashMap EntrySet
Map < Integer, String > coursesMap = new HashMap < Integer, String > ();
coursesMap.put(1, "C");
coursesMap.put(2, "C++");
coursesMap.put(3, "Java");
coursesMap.put(4, "Spring Framework");
coursesMap.put(5, "Hibernate ORM framework");
Iterator < Entry < Integer, String >> iterator = coursesMap.entrySet().iterator();
while (iterator.hasNext()) {
Entry < Integer, String > entry = iterator.next();
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
}
}
Output:
1
C
2
C++
3
Java
4
Spring Framework
5
Hibernate ORM framework
2. 使用 Iterator 遍历 HashMap KeySet
package com.java.tutorials.iterations;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
/**
* 在 Java 中遍历 HashMap 的5种最佳方法
* @author Ramesh Fadatare
*
*/
public class IterateHashMapExample {
public static void main(String[] args) {
Map < Integer, String > coursesMap = new HashMap < Integer, String > ();
coursesMap.put(1, "C");
coursesMap.put(2, "C++");
coursesMap.put(3, "Java");
coursesMap.put(4, "Spring Framework");
coursesMap.put(5, "Hibernate ORM framework");
// 2. 使用 Iterator 遍历 HashMap KeySet
Iterator < Integer > iterator = coursesMap.keySet().iterator();
while (iterator.hasNext()) {
Integer key = iterator.next();
System.out.println(key);
System.out.println(coursesMap.get(key));
}
}
}
Output:
1
C
2
C++
3
Java
4
Spring Framework
5
Hibernate ORM framework
3. 使用 For-each 循环遍历 HashMap
package com.java.tutorials.iterations;
import java.util.HashMap;
import java.util.Map;
/**
* 在 Java 中遍历 HashMap 的5种最佳方法
* @author Ramesh Fadatare
*
*/
public class IterateHashMapExample {
public static void main(String[] args) {
Map < Integer, String > coursesMap = new HashMap < Integer, String > ();
coursesMap.put(1, "C");
coursesMap.put(2, "C++");
coursesMap.put(3, "Java");
coursesMap.put(4, "Spring Framework");
coursesMap.put(5, "Hibernate ORM framework");
// 3. 使用 For-each 循环遍历 HashMap
for (Map.Entry < Integer, String > entry: coursesMap.entrySet()) {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
}
}
}
Output:
1
C
2
C++
3
Java
4
Spring Framework
5
Hibernate ORM framework
4. 使用 Lambda 表达式遍历 HashMap
package com.java.tutorials.iterations;
import java.util.HashMap;
import java.util.Map;
/**
* 在 Java 中遍历 HashMap 的5种最佳方法
* @author Ramesh Fadatare
*
*/
public class IterateHashMapExample {
public static void main(String[] args) {
Map < Integer, String > coursesMap = new HashMap < Integer, String > ();
coursesMap.put(1, "C");
coursesMap.put(2, "C++");
coursesMap.put(3, "Java");
coursesMap.put(4, "Spring Framework");
coursesMap.put(5, "Hibernate ORM framework");
// 4. 使用 Lambda 表达式遍历 HashMap
coursesMap.forEach((key, value) -> {
System.out.println(key);
System.out.println(value);
});
}
}
Output:
1
C
2
C++
3
Java
4
Spring Framework
5
Hibernate ORM framework
5. 使用 Stream API 遍历 HashMap
package com.java.tutorials.iterations;
import java.util.HashMap;
import java.util.Map;
/**
* 在 Java 中遍历 HashMap 的5种最佳方法
* @author Ramesh Fadatare
*
*/
public class IterateHashMapExample {
public static void main(String[] args) {
Map < Integer, String > coursesMap = new HashMap < Integer, String > ();
coursesMap.put(1, "C");
coursesMap.put(2, "C++");
coursesMap.put(3, "Java");
coursesMap.put(4, "Spring Framework");
coursesMap.put(5, "Hibernate ORM framework");
// 5. 使用 Stream API 遍历 HashMap
coursesMap.entrySet().stream().forEach((entry) - > {
System.out.println(entry.getKey());
System.out.println(entry.getValue());
});
}
}
Output:
1
C
2
C++
3
Java
4
Spring Framework
5
Hibernate ORM framework
HashMap 的相关教程
- 集合框架-HashMap 类[7]
- 集合框架-LinkedHashMap 类[8]
- 集合框架-TreeMap 类[9]
- 集合框架-EnumMap[10]
- 集合框架-WeakHashMap[11]
- 集合框架-IdentityHashMap[12]
Java中List集合的遍历
1 Iterator迭代器
使用迭代器Iterator进行遍历,这是直接根据List集合的一种自动遍历方式;
import java.util.ArrayList;
public class Demo03 {
public static void main(String[] args) {
ArrayList<News> list = new ArrayList<News>();
list.add(new News(1,"list1","a"));
list.add(new News(2,"list2","b"));
list.add(new News(3,"list3","c"));
list.add(new News(4,"list4","d"));
Iterator<News> iter = list.iterator();
while (iter.hasNext()) {
News s = (News) iter.next();
System.out.println(s.getId()+" "+s.getTitle()+" "+s.getAuthor());
}
}
}
-------------------------------------------
/**
* iterator
* 迭代器
* @param list
*/
public static void iteratorTest(List<Integer> list) {
long before = System.currentTimeMillis();
for (Iterator<Integer> iterator = list.iterator(); iterator.hasNext(); ) {
iterator.next();
}
long after = System.currentTimeMillis();
System.out.println("iterator for time=\t" + (after - before));
before = System.currentTimeMillis();
/**
* while 循环写法
*/
Iterator<Integer> iterator = list.iterator();
while (iterator.hasNext()) {
iterator.next();
}
after = System.currentTimeMillis();
System.out.println("iterator while time=\t" + (after - before));
}
2 for循环
指定下标长度,使用List集合的size()方法,进行for循环遍历,这种遍历方式最基础;
import java.util.ArrayList;
public class Demo01 {
/* for循环遍历List集合 */
public static void main(String[] args) {
ArrayList<News> list = new ArrayList<News>();
list.add(new News(1,"list1","a"));
list.add(new News(2,"list2","b"));
list.add(new News(3,"list3","c"));
list.add(new News(4,"list4","d"));
for (int i = 0; i < list.size(); i++) {
News s = (News)list.get(i);
System.out.println(s.getId()+" "+s.getTitle()+" "+s.getAuthor());
}
}
}
3 增强for
使用foreach遍历List,但不能对某一个元素进行操作(这种方法在遍历数组和Map集合的时候同样适用),这种遍历方式较为简洁;
import java.util.ArrayList;
public class Demo02 {
/* foreach循环遍历List集合 */
public static void main(String[] args) {
ArrayList<News> list = new ArrayList<News>();
list.add(new News(1,"list1","a"));
list.add(new News(2,"list2","b"));
list.add(new News(3,"list3","c"));
list.add(new News(4,"list4","d"));
for (News s : list) {
System.out.println(s.getId()+" "+s.getTitle()+" "+s.getAuthor());
}
}
}
4 for-each(java8才支持)
/**
* foreach
* foreach 最慢不推荐 java8 lambda
* @param list
*/
public static void forEachTest(List<Integer> list) {
long before = System.currentTimeMillis();
list.forEach(item -> {
System.out.println(item);
});
long after = System.currentTimeMillis();
System.out.println("list.forEach time=\t" + (after - before));
}
5 stream().forEach() 注意java8 才支持
/**
* stream foreach
* stream foreach java8 特有
* @param list
*/
public static void streamForEachTest(List<Integer> list) {
long before = System.currentTimeMillis();
list.stream().forEach(item -> {
System.out.println(item);
});
long after = System.currentTimeMillis();
System.out.println("list.stream().forEach time=\t" + (after - before));
}
6 parallelStream().forEach() 注意java8 才支持
/**
* stream foreach
* stream foreach java8 特有
* @param list
*/
public static void parallelStreamForEachTest(List<Integer> list) {
long before = System.currentTimeMillis();
list.parallelStream().forEach(item -> {
System.out.println(item);
});
long after = System.currentTimeMillis();
System.out.println("list.parallelStream().forEach time=\t" + (after - before));
}
Java 中 Set 的4中遍历方式
Set 和 List 遍历方式基本一致,Set 没有fori 的遍历方式
主测试方法
@Test
public void test(){
Set<Integer> set = new HashSet<>();
int n = 1000_0000;
for (int i = 0; i < n; i++) {
set.add(i);
}
System.out.println("======== 1 iterator ==========");
iteratorTest(set);
System.out.println("======== 2 增强for ==========");
forBoostTest(set);
System.out.println("======== 3 forEach 最耗时 java8 ==========");
forEachTest(set);
System.out.println("======== 4 stream forEach 比较耗时和增强for差不多 java8 ==========");
streamForEachTest(set);
}
测试结果
======== 1 iterator ==========
set.iterator() for time= 68
set.iterator() while time= 66
======== 2 增强for ==========
set.for Boost time= 75
======== 3 forEach 最耗时 java8 ==========
set.forEach time= 118
======== 4 stream forEach 比较耗时和增强for差不多 java8 ==========
set.stream().forEach() time= 71
1 迭代器方法
/**
* 1 iterator
* 迭代器
* @param set
*/
public static void iteratorTest(Set<Integer> set) {
long before = System.currentTimeMillis();
/**
* for 循环写法
*/
for (Iterator<Integer> iterator = set.iterator(); iterator.hasNext(); ) {
iterator.next();
}
long after = System.currentTimeMillis();
System.out.println("set.iterator() for time=\t" + (after - before));
before = System.currentTimeMillis();
/**
* while 循环写法
*/
Iterator<Integer> iterator = set.iterator();
while (iterator.hasNext()) {
iterator.next();
}
after = System.currentTimeMillis();
System.out.println("set.iterator() while time=\t" + (after - before));
}
2 增强for
/**
*
* 增强for
* @param set
*/
public static void forBoostTest(Set<Integer> set) {
long before = System.currentTimeMillis();
for (int item : set) {
System.out.println(item);
}
long after = System.currentTimeMillis();
System.out.println("set.for Boost time=\t" + (after - before));
}
3 set.forEach 注意:java8 才支持
/**
* foreach
* foreach 最慢不推荐 java8 lambda
* @param set
*/
public static void forEachTest(Set<Integer> set) {
long before = System.currentTimeMillis();
set.forEach(item -> {
System.out.println(item);
});
long after = System.currentTimeMillis();
System.out.println("set.forEach time=\t" + (after - before));
}
4 set.stream().forEach 注意:java8 才支持
/**
* stream foreach
* stream foreach java8 特有
* @param set
*/
public static void streamForEachTest(Set<Integer> set) {
long before = System.currentTimeMillis();
set.stream().forEach(item -> {
// System.out.println(item);
});
long after = System.currentTimeMillis();
System.out.println("set.stream().forEach() time=\t" + (after - before));
}
Collection.isEmpty()检测空
使用 Collection.size() 来检测空逻辑上没有问题,但是使用 Collection.isEmpty()使得代码更易读,并且可以获得更好的性能。任何 Collection.isEmpty() 实现的时间复杂度都是 O(1) ,但是某些 Collection.size() 实现的时间复杂度可能是 O(n) 。
反例:
if (collection.size() == 0) {
...
}
正例:
if (collection.isEmpty()) {
...
}
如果需要还需要检测 null ,可采用CollectionUtils.isEmpty(collection)和CollectionUtils.isNotEmpty(collection)。
集合初始化尽量指定大小
Java 的集合类用起来十分方便,但是看源码可知,集合也是有大小限制的。每次扩容的时间复杂度很有可能是 O(n) ,所以尽量指定可预知的集合大小,能减少集合的扩容次数。
反例:
int[] arr = new int[]{1, 2, 3};
List<Integer> list = new ArrayList<>();
for (int i : arr) {
list.add(i);
}
正例:
int[] arr = new int[]{1, 2, 3};
List<Integer> list = new ArrayList<>(arr.length);
for (int i : arr) {
list.add(i);
}
字符串拼接使用 StringBuilder
一般的字符串拼接在编译期 java 会进行优化,但是在循环中字符串拼接, java 编译期无法做到优化,所以需要使用 StringBuilder 进行替换。
反例:
String s = "";
for (int i = 0; i < 10; i++) {
s += i;
}
正例:
String a = "a";
String b = "b";
String c = "c";
String s = a + b + c; // 没问题,java编译器会进行优化
StringBuilder sb = new StringBuilder();
for (int i = 0; i < 10; i++) {
sb.append(i); // 循环中,java编译器无法进行优化,所以要手动使用StringBuilder
}
使用String.valueOf(value)代替""+value
当要把其它对象或类型转化为字符串时,使用 String.valueOf(value) 比""+value 的效率更高。
反例:
int i = 1;
String s = "" + i;
正例:
int i = 1;
String s = String.valueOf(i);