Java 中遍历集合的最佳解决方案
Aidan Engineer

进行集合的遍历无非就是 for(forEach), Iterator 两种方式,其实迭代器被设计出来就是为了方便集合的遍历,但为什么要这么使用,以及一些骚操作在这里做一个总结

ArrayList

直接看综合的测试代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;

/**
* @author Aidan
* @createTime 2021/11/16 16:20
* @GitHub github.com/huaxin0304
* @Blog aidanblog.top
*/

public class TraversalList {
private static final int MAX_SIZE = 10000;

public static void main(String[] args) {
// 构建初始 ArrayList
List<Integer> arrayList = new ArrayList<Integer>();
for (int i = 0; i < MAX_SIZE; i++) {
arrayList.add(i);
}

// for 循环测试
long start = System.currentTimeMillis();
for (int i = 0; i < MAX_SIZE; i++) {
Integer integer = arrayList.get(i);
System.out.print(integer.toString() + " ");
}
long resultFor = System.currentTimeMillis() - start;

// forEach 遍历测试
start = System.currentTimeMillis();
for (Integer integer : arrayList) {
System.out.print(integer + " ");
}
long resultForEach = System.currentTimeMillis() - start;

// Iterator 遍历测试
start = System.currentTimeMillis();
Iterator<Integer> iterator = arrayList.iterator();
while (iterator.hasNext()) {
System.out.print(iterator.next() + " ");
}
long resultIterator = System.currentTimeMillis() - start;

System.out.println("\n\n=============== Result ================\n");
System.out.println(resultFor);
System.out.println(resultForEach);
System.out.println(resultIterator);

}
}

测试结果几次都不同,但时间花费基本上大差不差,看起来用哪个无所谓,不过 forEach 也是基于 Iterator 来实现,相较于 for 和 Iterator 来说,其语法更加简洁,使用时不用考虑下标,所以如果只是单纯的进行遍历元素, 推荐使用 forEach,如果有遍历修改的需求一般会使用 for 循环来实现,但如果添加或是向前遍历可以使用 ListIterator 进行操作

1
2
3
4
5
6
7
8
9
10
11
12
ListIterator<Integer> integerListIterator = arrayList.listIterator();

while (integerListIterator.hasNext()) {
// 为集合中的每个元素后添加一个 -1
integerListIterator.add(-1);
integerListIterator.next();
}

// 此时迭代器游标处于最后
while (integerListIterator.hasPrevious()) {
System.out.println(integerListIterator.previous());
}

LinkedList

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
private static final int MAX_SIZE = 10000;

public static void main(String[] args) {
List<Integer> linked = new LinkedList<>();

for (int i = 0; i < MAX_SIZE; i++) {
linked.add(i);
}

long start = System.currentTimeMillis();
for (int i = 0; i < linked.size(); i++) {
System.out.print(linked.get(i));
}
long resultFor = System.currentTimeMillis() - start;

start = System.currentTimeMillis();
for (Integer integer : linked) {
System.out.println(integer);
}
long resultForEach = System.currentTimeMillis() - start;

start = System.currentTimeMillis();
Iterator<Integer> iterator = linked.iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next());
}
long resultIterator = System.currentTimeMillis() - start;

System.out.println("\n\n========== Result =========\n");
System.out.println(resultFor);
System.out.println(resultForEach);
System.out.println(resultIterator);
}

这时花费的时间就优点意思了,for 使用的时间比其他两种方式加起来都多,至于 forEach 和 Iterator 大致相同

原因就是 LinkedList 不支持随机存储,大量的 get() 不过是每次的遍历到指定的位置,也就是说数据规模越大,花费的时间越长

HashMap

遍历 HashMap 有三种方式,使用 keySet 或者 valueSet 进行遍历,适合只遍历一种类型的情况下进行使用,其次就是使用 entrySet 进行所有的遍历,还有就是使用 EntrySet 的 Iterator 进行遍历,还有不常使用的一种就是先使用 KeySet 获取所有的键,然后使用键去获取对应的 Value,实际使用性能太低,所以不做考虑, 推荐使用 entrySet 的方式进行遍历

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;

/**
* @author Aidan
* @createTime 2021/11/16 20:14
* @GitHub github.com/huaxin0304
* @Blog aidanblog.top
*/

public class TraversalMap {
public static void main(String[] args) {
HashMap<String, String> map = new HashMap<>(10);

for (int i = 0; i < 10; i++) {
map.put(String.valueOf(i), String.valueOf(Math.random()));
}

// 使用 KeySet 或者 ValSet 进行遍历
for (String s : map.keySet()) {
System.out.println(s);
}
System.out.println("===========");
for (String value : map.values()) {
System.out.println(value);
}

// 使用 EntrySet 进行遍历
for (Map.Entry<String, String> entry : map.entrySet()) {
System.out.println(entry.getKey() + ":entry:" + entry.getValue());
}

// 使用 Iterator 进行遍历
Iterator<Map.Entry<String, String>> iterator = map.entrySet().iterator();
while (iterator.hasNext()) {
System.out.println(iterator.next().getKey() + ":iterator:" + iterator.next().getValue());
}
}
}

总结

  • ArrayList 为了简洁方便使用 forEach
  • LinkedList 因为链式存储的原因使用迭代器进行访问
  • HshMap 使用 EntrySet 的方式进行遍历性能最佳同时适用于大多数情况
  • 本文标题:Java 中遍历集合的最佳解决方案
  • 本文作者:Aidan
  • 创建时间:2021-11-16 16:15:20
  • 本文链接:https://aidanblog.top/native_code-traversal_collection/
  • 版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
 评论