List list = new ArrayList(); for (Object item : list) { System.out.println(item.toString()); }相当于: List list = new ArrayList(); Object obj; for (Iterator iterator = list.iterator(); iterator.hasNext();) { obj = iterator.next(); System.out.println(obj.toString()) }
反编译一下可以看到里面还是通过迭代器来实现的。 文档里也有说明: public interface Iterable<T>实现这个接口允许对象成为 "foreach" 语句的目标。 编译之后通过Iterator<T> iterator()方法获得的迭代器来实现循环访问。
对于ArrayList,Vector 其核心是一个数组, 如果明确知道List的实例是ArrayList,Vector,当然用 for(int i=0; i<lst.size();i++){} 这种方式是最快的. 当然用Iterator 的话,其实是相关无几,Iterator 基本上都是指针操作, Iterator本身的处理会增加一点点的开销,跟踪一下源码就可以知道.Iterator 好处:通用,对于所有集合,使用Iterator性能都一样, 客户端自身不维护遍历集合的"指针",所有的内部状态(如当前元素位置,是否有下一个元素)都由Iterator来维护,而这个Iterator由集合类通过工厂方法生成,因此,它知道如何遍历整个集合。 客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。for(i=0;...) 方法有一个缺点: 如果List的实例是LinkedList等非"数组"存储方式的时候,遍历集合的开销会差别很大! 就以LinkedList来说,以下是get(i)方法来取元素的主要代码, 我们可以看到,LinkedList 内的get(i)方法,用了循环方式来返回元素,性能肯定会差. if (index < 0 || index >= size) throw new IndexOutOfBoundsException("Index: "+index+ ", Size: "+size); Entry<E> e = header; if (index < (size >> 1)) { for (int i = 0; i <= index; i++) e = e.next; } else { for (int i = size; i > index; i--) e = e.previous; } return e;
楼主,我用100000最小数据测试了一下:import java.util.*; public class CMPfor { final long N = 1000000; private ArrayList<Integer> aT = new ArrayList<Integer>(); private LinkedList<Integer> LT = new LinkedList<Integer>(); public CMPfor(){ for(int i = 0; i < N; i++){ aT.add(i); } for(int i = 0; i < N; i++){ LT.add(i); } } public void forTest(List<Integer> t){ for(int i = 0; i < t.size();i++){ t.get(i); } } public void foreachTest(List<Integer> t){ for(int j : t){
} } public void iteratorTest(List<Integer> t){ Iterator it = t.iterator(); while(it.hasNext()){ it.next(); } } public void whileTest(List<Integer> t){ int i = 0; while(i < N){ t.get(i); i++; } } public static void main(String[] args){
12楼不知道想表达什么, 你想说while比for 效率高吗?结论是这样的, 1.for 与 while 性能是一样的,这个很多人都测试过了.2. 另外 foreach 与 for + iterator 也是一样的,为什么一样上面已经说了,编译器最终把foreach编译成for + iterator,而且已经测试过了,事实跟理论一致.3.至于LinkedList为什么这么长时间, 我在6楼已经说得很清楚了. 所以说for + get(i) 方法不够"通用"4. foreach(for + iterator) 与 for + get(i) 性能差别很少(6楼已经说过了),iterator因为对所有集合效率几乎一样,所以很通用, 如果你的程序是面向接口的,一般就得用比较通用的iterator, 绝大多数情况下,我们都不必介意效率有那么一点儿差别, 我们需要知道有这么一点儿差别就是了. 以下对5000000条记录的ArrayList的测试结果,已经运行了十几次,每次结果差不多: 1.for + get(i)方法: 94 2.Iterator(foreach)方法:265 3.While + get(i)方法:94 4.for iterator方法:281 package myTest;import java.util.ArrayList; import java.util.HashMap; import java.util.Iterator; import java.util.LinkedList; import java.util.List; import java.util.SortedMap; import java.util.Vector;public class Test { public static void main(String[] args) { List<Integer> list = new ArrayList<Integer>(); for(int i=0;i<5000000 ;i++){ list.add(11); }
int size= list.size(); int c1=1; long start = System.currentTimeMillis(); for(int i=0;i<size;i++){ c1 = list.get(i); } long end = System.currentTimeMillis()-start; System.out.println("for + get(i)方法: " + end);
写段程序测试下: public void testForEach() { List<String> list = new ArrayList<String>(); int startNumber = 2; for (int i = 10; i < 25; i++) { double maxSize = Math.pow(startNumber, i); for (int index = 0; index < maxSize; index++) { list.add(""); } Long start = System.currentTimeMillis(); for (int jj = 0; jj < maxSize; jj++) { String result = list.get(jj); } Long end = System.currentTimeMillis(); long total1 = (end - start); start = System.currentTimeMillis(); for (String result : list) { } end = System.currentTimeMillis(); long total2 = (end - start); System.out.println(i + ": totalSzie: " + maxSize + ", and get took: " + total1 + ", while forEach took: " + total2); list.clear(); } }结果如下: 10: totalSzie: 1024.0, and get took: 0, while forEach took: 0 11: totalSzie: 2048.0, and get took: 0, while forEach took: 0 12: totalSzie: 4096.0, and get took: 0, while forEach took: 0 13: totalSzie: 8192.0, and get took: 0, while forEach took: 0 14: totalSzie: 16384.0, and get took: 0, while forEach took: 0 15: totalSzie: 32768.0, and get took: 15, while forEach took: 0 16: totalSzie: 65536.0, and get took: 0, while forEach took: 0 17: totalSzie: 131072.0, and get took: 0, while forEach took: 0 18: totalSzie: 262144.0, and get took: 0, while forEach took: 15 19: totalSzie: 524288.0, and get took: 0, while forEach took: 31 20: totalSzie: 1048576.0, and get took: 15, while forEach took: 32 21: totalSzie: 2097152.0, and get took: 31, while forEach took: 79 22: totalSzie: 4194304.0, and get took: 62, while forEach took: 141
for (Object item : list) {
System.out.println(item.toString());
}相当于: List list = new ArrayList();
Object obj;
for (Iterator iterator = list.iterator(); iterator.hasNext();) {
obj = iterator.next();
System.out.println(obj.toString())
}
文档里也有说明:
public interface Iterable<T>实现这个接口允许对象成为 "foreach" 语句的目标。
编译之后通过Iterator<T> iterator()方法获得的迭代器来实现循环访问。
客户端从不直接和集合类打交道,它总是控制Iterator,向它发送"向前","向后","取当前元素"的命令,就可以间接遍历整个集合。for(i=0;...) 方法有一个缺点: 如果List的实例是LinkedList等非"数组"存储方式的时候,遍历集合的开销会差别很大! 就以LinkedList来说,以下是get(i)方法来取元素的主要代码, 我们可以看到,LinkedList 内的get(i)方法,用了循环方式来返回元素,性能肯定会差. if (index < 0 || index >= size)
throw new IndexOutOfBoundsException("Index: "+index+
", Size: "+size);
Entry<E> e = header;
if (index < (size >> 1)) {
for (int i = 0; i <= index; i++)
e = e.next;
} else {
for (int i = size; i > index; i--)
e = e.previous;
}
return e;
再看一下,ArrayList 的 get(index) 方法:
return (E) elementData[index];因为内部是数组存储的,所以直接返回数组元素,所以肯定是最快的方法 .
oh,no, 搞错了, 只看到for 没看到到foreach. 而且是针对集合,而不是List.foreach 不知内部是不会根据不同实例类型作优化,如果没有,则可能内部就是用Iterator方法(具体可以试试跟踪一下源代码),如果这样效率应该是一样的.
谢谢,提醒,我试了,可以告诉楼主,for(xx:col) 这种形式编译后就是等于 for(Iterator iterator = list.iterator(); iterator.hasNext();)
所以效率是一样的。另贴一下,测试代码说明一下for + get(i) 的方法 与 Iterator 的性能差别.
public static void main(String[] args)
{ List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<5000000 ;i++){
list.add(11);
}
long start = System.currentTimeMillis();
int size= list.size();
int c1=1;
for(int i=0;i<size;i++){
c1 = list.get(i);
}
System.out.println("for + get(i)方法: "
+ (System.currentTimeMillis()-start));
long start2 = System.currentTimeMillis();
for(int c2:list){
}
System.out.println("Iterator(foreach)方法:"
+ (System.currentTimeMillis()-start2)); }
public class CMPfor
{
final long N = 1000000;
private ArrayList<Integer> aT = new ArrayList<Integer>(); private LinkedList<Integer> LT = new LinkedList<Integer>(); public CMPfor(){
for(int i = 0; i < N; i++){
aT.add(i);
}
for(int i = 0; i < N; i++){
LT.add(i);
}
} public void forTest(List<Integer> t){
for(int i = 0; i < t.size();i++){
t.get(i);
}
}
public void foreachTest(List<Integer> t){
for(int j : t){
}
} public void iteratorTest(List<Integer> t){
Iterator it = t.iterator();
while(it.hasNext()){
it.next();
}
}
public void whileTest(List<Integer> t){
int i = 0;
while(i < N){
t.get(i);
i++;
}
} public static void main(String[] args){
CMPfor cf = new CMPfor(); long a,b; System.out.println("ArrayList Test:");
a=System.currentTimeMillis(); cf.forTest(cf.aT); b=System.currentTimeMillis(); System.out.println("forTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.foreachTest(cf.aT); b=System.currentTimeMillis(); System.out.println("foreachTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.iteratorTest(cf.aT); b=System.currentTimeMillis(); System.out.println("iteratorTest: "+(b-a)+"ms");
a=System.currentTimeMillis(); cf.whileTest(cf.aT); b=System.currentTimeMillis(); System.out.println("whileTest: "+(b-a)+"ms");
System.out.println("LinkedList Test:");
a=System.currentTimeMillis(); cf.forTest(cf.LT); b=System.currentTimeMillis(); System.out.println("forTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.foreachTest(cf.LT); b=System.currentTimeMillis(); System.out.println("foreachTest: "+(b-a)+"ms"); a=System.currentTimeMillis(); cf.iteratorTest(cf.LT); b=System.currentTimeMillis(); System.out.println("iteratorTest: "+(b-a)+"ms");
a=System.currentTimeMillis(); cf.whileTest(cf.LT); b=System.currentTimeMillis(); System.out.println("whileTest: "+(b-a)+"ms");
}
}
结果如下:
ArrayList Test:
forTest: 10ms
foreachTest: 20ms
iteratorTest: 10ms
whileTest: 10ms
LinkedList Test:
forTest: 108135ms
foreachTest: 10ms
iteratorTest: 10ms
whileTest: 120644ms
另一组运行结果:
ArrayList Test:
forTest: 10
foreachTest: 10
iteratorTest: 20
whileTest: 0
LinkedList Test:
forTest: 105852
foreachTest: 10
iteratorTest: 20
whileTest: 104851事实证明:
不同的集合类型处理的时间不同
LinkedList 不要用for和while
foreach比Iterator快
ArayList中,遍历速度:while>for>foreach
public void forTest(List<Integer> t){
for(int i = 0; i < t.size();i++){
t.get(i);
}
}
public void foreachTest(List<Integer> t){
for(int j : t){
}
}
for测试直接用t.get(i);
foreach测试却
for(int j : t){
}
中间增加了Integer到int的转换过程。
代码都是一样的,性能差距是怎么来的呢?
1.for 与 while 性能是一样的,这个很多人都测试过了.2. 另外 foreach 与 for + iterator 也是一样的,为什么一样上面已经说了,编译器最终把foreach编译成for + iterator,而且已经测试过了,事实跟理论一致.3.至于LinkedList为什么这么长时间, 我在6楼已经说得很清楚了. 所以说for + get(i) 方法不够"通用"4. foreach(for + iterator) 与 for + get(i) 性能差别很少(6楼已经说过了),iterator因为对所有集合效率几乎一样,所以很通用, 如果你的程序是面向接口的,一般就得用比较通用的iterator, 绝大多数情况下,我们都不必介意效率有那么一点儿差别, 我们需要知道有这么一点儿差别就是了. 以下对5000000条记录的ArrayList的测试结果,已经运行了十几次,每次结果差不多:
1.for + get(i)方法: 94
2.Iterator(foreach)方法:265
3.While + get(i)方法:94
4.for iterator方法:281
package myTest;import java.util.ArrayList;
import java.util.HashMap;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.List;
import java.util.SortedMap;
import java.util.Vector;public class Test {
public static void main(String[] args)
{ List<Integer> list = new ArrayList<Integer>();
for(int i=0;i<5000000 ;i++){
list.add(11);
}
int size= list.size();
int c1=1;
long start = System.currentTimeMillis();
for(int i=0;i<size;i++){
c1 = list.get(i);
}
long end = System.currentTimeMillis()-start;
System.out.println("for + get(i)方法: " + end);
start = System.currentTimeMillis();
for(int c2:list){
}
end = System.currentTimeMillis()-start;
System.out.println("Iterator(foreach)方法:" + end);
int i = 0;
size = list.size();
start = System.currentTimeMillis();
while(i<size){
c1 = list.get(i);
i++;
}
end = System.currentTimeMillis()-start;
System.out.println("While + get(i)方法:" + end);
start = System.currentTimeMillis();
for(Iterator iterator = list.iterator(); iterator.hasNext();) {
c1 = (Integer) iterator.next();
}
end = System.currentTimeMillis()-start;
System.out.println("for iterator方法:" + end);
}
}
public void testForEach() {
List<String> list = new ArrayList<String>();
int startNumber = 2;
for (int i = 10; i < 25; i++) {
double maxSize = Math.pow(startNumber, i);
for (int index = 0; index < maxSize; index++) {
list.add("");
}
Long start = System.currentTimeMillis();
for (int jj = 0; jj < maxSize; jj++) {
String result = list.get(jj);
}
Long end = System.currentTimeMillis();
long total1 = (end - start); start = System.currentTimeMillis();
for (String result : list) { }
end = System.currentTimeMillis();
long total2 = (end - start);
System.out.println(i + ": totalSzie: " + maxSize + ", and get took: "
+ total1 + ", while forEach took: " + total2);
list.clear();
}
}结果如下:
10: totalSzie: 1024.0, and get took: 0, while forEach took: 0
11: totalSzie: 2048.0, and get took: 0, while forEach took: 0
12: totalSzie: 4096.0, and get took: 0, while forEach took: 0
13: totalSzie: 8192.0, and get took: 0, while forEach took: 0
14: totalSzie: 16384.0, and get took: 0, while forEach took: 0
15: totalSzie: 32768.0, and get took: 15, while forEach took: 0
16: totalSzie: 65536.0, and get took: 0, while forEach took: 0
17: totalSzie: 131072.0, and get took: 0, while forEach took: 0
18: totalSzie: 262144.0, and get took: 0, while forEach took: 15
19: totalSzie: 524288.0, and get took: 0, while forEach took: 31
20: totalSzie: 1048576.0, and get took: 15, while forEach took: 32
21: totalSzie: 2097152.0, and get took: 31, while forEach took: 79
22: totalSzie: 4194304.0, and get took: 62, while forEach took: 141