一个简单的实验,Java数组遍历

Java提供了多种数组遍历的方法,从传统的for while到新的foreach. 那么,倒底该选择哪种遍历方式呢,也许很多人不会刻意关心这类问题,人们大多凭个人习惯来选择.

本人以前也不曾注意过,只不过在玩了project euler之后,逐渐开始关心起java程序的性能来(我也不再用C++写了,这种小游戏没必要).

 

于是乎就做了一个对比试验,在数组中放置从1到1m的数,然后将它们累加起来,计算时间.

为了说明问题,我将分三种方式逐一对比,

1. 使用传统的for循环

2. 使用java的exception

3. 使用foreach

 

import callback.Callback;


public class Foo {

	final static int INIT_NUM = 1000000;
	static int array[] = new int[INIT_NUM];
	
	public static void main(String[] args) {
		for (int i = 0; i < INIT_NUM; i ++)
			array[i] = i + 1;
		
		PerformDiag.perform(new Callback() {
			
			@Override
			public void execute() {
				testLoop();
			}
		}, PerformDiag.NANO_PREC);
		
		PerformDiag.perform(new Callback() {
			
			@Override
			public void execute() {
				testException();
			}
		}, PerformDiag.NANO_PREC);
		
		PerformDiag.perform(new Callback() {
			
			@Override
			public void execute() {
				testForeach();
			}
		}, PerformDiag.NANO_PREC);
	}
	
	static void testLoop()
	{
		int sum = 0;
		for (int i = 0; i < array.length; i++)
			sum += array[i];
	}
	
	static void testException()
	{
		int sum = 0, i = 0;
		while(true)
		{
			try
			{
				sum += array[i++];
			}
			catch (IndexOutOfBoundsException e) { break; }
		}
	}
	
	static void testForeach()
	{
		int sum = 0, i = 0;
		for (Integer a : array) {
			sum += a;
		}
	}
}


这里PerformDiag是一个简单的性能诊断,只是将回调前后的时间差算出来,精度可以选择milli或nano.

执行结果如下,

use time = 4817412 nano secs
use time = 3322288 nano secs
use time = 20045063 nano secs


可以看到,传统的for循环排在第二位,使用了exception的速度最快,而foreach则远远慢于前两者.

 

这个结果很容易解释,由于java本身有边界溢出异常,事实上语言框架已经在帮你检查循环条件了,for循环则再一次执行了这个动作,肯定会浪费一些时间.

而如果使用while(true)这样的形式,编译器会优化成一个短跳转指令,这样在代码里就没有条件判断,直到当exception被抛出我们才跳出循环.

而foreach虽然貌似也没有条件判断,但是它只限于wrapper类,频繁的构造对象肯定会对速度产生影响,少打几个字,会付出大量的性能代价.

 

总的来说,如果你的Java程序对性能比较感冒,建议使用while(true) + exception的组合,理论上这种写法速度更快.

你可能感兴趣的:(一个简单的实验,Java数组遍历)