进行集合的遍历无非就是 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;
public class TraversalList { private static final int MAX_SIZE = 10000;
public static void main(String[] args) { List<Integer> arrayList = new ArrayList<Integer>(); for (int i = 0; i < MAX_SIZE; i++) { arrayList.add(i); }
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;
start = System.currentTimeMillis(); for (Integer integer : arrayList) { System.out.print(integer + " "); } long resultForEach = System.currentTimeMillis() - start;
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()) { 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;
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())); }
for (String s : map.keySet()) { System.out.println(s); } System.out.println("==========="); for (String value : map.values()) { System.out.println(value); }
for (Map.Entry<String, String> entry : map.entrySet()) { System.out.println(entry.getKey() + ":entry:" + entry.getValue()); }
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 的方式进行遍历性能最佳同时适用于大多数情况