对于性能优化的知识点来说,太宽泛了。博主本人一直很注重这方面的学习,而对于性能优化,包括非常非常多的方面,比如:I/O优化、网络运行优化、内存优化、数据结构优化、代码层面优化、UI渲染优化、CPU资源使用优化、异常处理优化等。..本文根据博主自己的理解,说说Android开发中一些可以优化的地方。ArrayList和VectorArrayList和Vector都是内部实现的带有数组的列表。是安全的,Vector中的大部分方法都是内部同步的,是线程安全的。既然是线程安全的,性能上肯定是不如ArrayList的(当然思路一定是对的),但是要看哪一方面,ArrayList在add、get、remove等操作上肯定比Vector高效,但在内存方面,Vector的表现要优于ArrayList。这归根结底是ArrayList的扩容策略造成的,后面会分析。实现RandomAccess接口的集合使用fori遍历。首先说说List集合的遍历方式。共有三种类型:foreach、iterator和fori。在开发中,一般需要遍历的时候,foreach肯定是首选,因为效率高。这种看法是对的,但需要分场合。下面是一个包含100w条数据的ArrayList集合,我用三种方式测试:longstart=System.currentTimeMillis();for(inti=0;iiterator=data.iterator();start=System.currentTimeMillis();while(iterator.hasNext()){iterator.next();}end=System.currentTimeMillis();Log.v("zxy","迭代器成本:"+(end-start));11-1909:11:44.2761418-1418/?V/zxy:foricost:3011-1909:11:44.3801418-1418/?V/zxy:foreachcost:10511-1909:11:44.4761418-1418/?V/zxy:iteratorcost:95而我们通常所说的高效foreach并不尽如人意在遍历中,fori效率最高。这是因为ArrayList和Vector集合的内部实现都是数组实现的,所以随机访问的速度非常快。对于可以随机访问的列表,JDK为它们提供了实现的RandomAccess接口,表示支持快速随机访问。而当遍历1w条数据的LinkedList集合时:11-1909:33:23.9841737-1737/?V/zxy:foricost:35111-1909:33:23.9881737-1737/?V/zxy:foreachcost:211-1909:33:23.9921737-1737/?V/zxy:iteratorcost:4,那么foreach性能最好,所以对于实现了RandomAccess接口的数组或者List,fori遍历性能最好,对于LinkedList等实现的集合链表遍历时使用foreach或者iterator的性能是最好的,因为foreach的实现是通过iterator来实现的。我们可以这样判断是通过哪种方式遍历List:if(listinstanceofRandomAccess){for(inti=0;iiterator=list.iterator();while(iterator.hasNext()){iterator.next();}}预测容量时,尽量在构造ArrayList时指定初始大小。ArrayList的内部扩容策略是当它存储的元素个数超过了它现有的大小时,它会扩容1.5倍的容量,也就是说,如果ArrayList的当前容量是10000,那么当它需要存储另一个元素的时候,也就是第10001个元素,由于容量不足会扩容一次,而扩容后的ArrayList容量改为15000,再多一个元素5000个元素的空间就太多了,浪费占用内存资源,而且扩容也会造成整个数组的内存拷贝,而ArrayList集合的默认大小是10,所以合理设置ArrayList的容量可以避免集合的扩容。ArrayList内部扩展和数组复制代码为:Object[]newArray=newObject[s+(s<(MIN_CAPACITY_INCREMENT/2)?MIN_CAPACITY_INCREMENT:s>>1)];System.arraycopy(a,0,newArray,0,s);阵列=一个=新阵列;而Vector的内部扩展策略是按需扩展,每次+1:if(capacityIncrement<=0){if((adding=elementData.length)==0){adding=1;}}else{adding=capacityIncrement;}E[]newData=newElementArray(elementData.length+adding);同样,很多Map集合也有自己的扩展策略。比如HashMap每次扩容后新增的容量等于原来的容量*2。我们经常用到的字符串拼接的StringBuffer和StringBuilder内部,其实是有扩容策略的,默认是扩容到原来的1.5倍。所以,在这些需要扩展的API上,如果事先知道数据的大小,就应该提前设置好。这样既可以避免扩容造成的空间浪费,也可以避免内部调用System.arraycopy()复制大量数据。如果程序需要通过索引下标对List进行随机访问,应优先使用ArrayList和Vector,尽量不用LinkedList。ArrayList虽然在内存方面不如Vector,但是在数据操作上效率很高,尤其是在Android等手机上。在设备上,牺牲一点空间换取时间是可取的,涉及到线程安全,使用Vector。如果一个方法不需要使用对象的成员,那么将方法设置为static调用方法比调用对象上的方法快15%~20%,因为从方法签名可以看出方法调用不会影响对象的状态巧妙使用final关键字final关键字一般用的比较多的是定义常量和方法,而大多数人对final的理解往往是在不可变性方面,final对性能优化也有很大的作用。例如:staticintAGE=10;后面引用10的时候,会有一个字段查找的过程。对于int类型,就是查找方法区的整型常量池,对于final常量,则省略这个过程完成,例如:staticfinalintAGE=10;在使用AGE的地方,10会直接被替换掉。不过,对于上面的优化技巧来说,只对基本类型和String类型有效,对其他引用类型无效,但是在声明常量的时候加上staticfinal仍然是我们的一个好习惯。对于final关键字,还有一个强大的作用,就是为那些使用频率高,已经确定为final状态的方法定义final。这样做有什么好处?说这个之前,先说说java中方法的执行过程。当调用一个方法时,首先,这个方法会被压入栈中。执行完成后,将此方法出栈,释放资源。这个进程的内部过程其实就是内存地址的传递过程。当执行入栈方法时,实际上是将程序的执行地址转移到方法中存放的内存中。在地址中,在做这个操作之前,还有保存原程序执行的内存地址的过程。当方法执行完出栈后,程序会根据保存的地址继续执行,这个过程就是方法调用过程。所以一个方法的调用过程其实是需要空间和时间的,频繁调用同一个方法的优化其实是使用了inline方法。说到内联函数,内联函数其实是在编译的时候优化的。编译器会在调用的地方直接将标记为inline的函数替换成整个函数体,这样就节省了函数调用消耗的时间资源减少,但是换来的是目标代码量的增加,所以内联的优化策略实际上是一种用空间换取时间的策略。对于移动端来说,巧妙的使用inlineLinkedfunctions其实是非常有好处的。而如果一个函数变成了内联函数,就定义为final,这样在编译程序的时候,编译器会自动优化内联final函数,然后直接展开函数体,供调用函数时使用。综上所述,并不是内联函数越多越好。一方面确实提高了我们程序的运行效率,但是另一方面,如果使用过多的内联函数,反而会弄巧成拙,而且某个方法的方法体越来越大,并且对于一些方法体比较大的方法,内联展开的时间可能会超过方法调用的时间,所以这不仅不会提供性能,反而会降低该有的性能。总的来说,我们可以对那些使用频率高,已经确定为final状态,方法体小的方法使用final修饰符来提高程序的性能。优先使用系统提供的代码,不要自己写。系统内置了很多非常方便的API供我们使用,比如:System、Arrays、Collections、String等,还有很多内置的方法API,比我们自己手写方便多了,除了这个在另外对于Android来说,很多API都是使用底层的C/C++实现,所以效率比我们自己写的要快。同样,对于系统API,DVM也经常使用内联方法来提高效率。小心使用异常。不是不使用异常,而是在程序中通过抛出异常来执行某些操作。比如有些人会通过强行抛出异常来中断某些操作。因为fillInStackTrace();方法会在抛出异常时执行,该方法的作用是重新调整栈,因此避免使用异常是很有必要的。