尽量使用StringBuilder和StringBuffer进行字符串连接
StringBuffer,StringBuilder 的区别
StringBuffer,StringBuilder 的区别在于:java.lang.StringBuffer 线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。StringBuilder 与该类相比,通常应该优先使用 StringBuilder 类,因为她支持所有相同的操作,但由于她不执行同步,所以速度更快。为了获得更好的性能,在构造 StringBuffer 或 StringBuilder 时应尽量指定她的容量。当然如果不超过 16 个字符时就不用了。 相同情况下,使用 StringBuilder 比使用 StringBuffer 仅能获得 10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用 StringBuffer。
通过 StringBuffer 的构造函数来设定他的初始化容量,可以明显提升性能。
StringBuffer 的默认容量为 16,当 StringBuffer 的容量达到最大容量时,她会将自身容量增加到当前的 2 倍+2,也就是 2*n+2。无论何时,只要 StringBuffer 到达她的最大容量,她就不得不创建一个新的对象数组,然后复制旧的对象数组,这会浪费很多时间。所以给StringBuffer 设置一个合理的初始化容量值,是很有必要的!
尽量确定StringBuffer的容量
StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再 丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能。
如:StringBuffer buffer = new StringBuffer(1000);
对于常量字符串,用‘string‘ 代替 ‘stringbuffer‘
常量字符串并不需要动态改变长度。
尽量避免使用二维数组
二维数据占用的内存空间比一维数组多得多,大概10倍以上。
在使用集合的时候,优先选择SparseArray,尽量用Android提供的SparseArray来代替HashMap
使用实体类比接口好
假设你有一个HashMap对象,你可以将它声明为HashMap或者Map:
Map map1 = new HashMap(); HashMap map2 = new HashMap();
哪个更好呢?
按照传统的观点Map会更好些,因为这样你可以改变他的具体实现类,只要这个类继承自Map接口。传统的观点对于传统的程序是正确的,但是它并不适合嵌入式系统。
调 用一个接口的引用会比调用实体类的引用多花费一倍的时间。如果HashMap完全适合你的程序,那么使用Map就没有什么价值。如果有些地方你不能确定, 先避免使用Map,剩下的交给IDE提供的重构功能好了。(当然公共API是一个例外:一个好的API常常会牺牲一些性能)
ArrayList & LinkedList
一 个是线性表,一个是链表,
一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指 针,
添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据,不过这是理论性分析,事实未必如此,重要的是理解好2 者得数据结构,对症下药。
单线程应尽量使用HashMap、ArrayList
HashTable、Vector等使用了同步机制,降低了性能。
尽量合理的创建HashMap
当你要创建一个比较大的hashMap时,充分利用另一个构造函数
public HashMap(int initialCapacity, float loadFactor)
避 免HashMap多次进行了hash重构,扩容是一件很耗费性能的事,在默认中initialCapacity只有16,而 loadFactor是 0.75,需要多大的容量,你最好能准确的估计你所需要的最佳大小,同样的Hashtable,Vectors也是一样的道理。
避免使用枚举
枚举变量非常方便,但不幸的是它会牺牲执行的速度和并大幅增加文件体积。例如:
public class Foo { public enum Shrubbery { GROUND, CRAWLING, HANGING } }
会产生一个900字节的.class文件(FooShubbery.class)。在它被首次调用时,这个类会调用初始化方法来准备每个枚举变量。每个枚举项都会被声明成一个静态变量,并被赋值。然后将这些静态变量放在一个名为”VALUES”的静态数组变量中。而这么一大堆代码,仅仅是为了使用三个 整数。
这样:Shrubbery shrub =Shrubbery.GROUND;会引起一个对静态变量的引用,如果这个静态变量是final int,那么编译器会直接内联这个常数。
一方面说,使用枚举变量可以让你的API更出色,并能提供编译时的检查。所以在通常的时候你毫无疑问应该为公共API选择枚举变量。但是当性能方面有所限制的时候,你就应该避免这种做法了。
有些情况下,使用ordinal()方法获取枚举变量的整数值会更好一些,举例来说:
for(int n =0; n < list.size(); n++) { if(list.items[n].e == MyEnum.VAL_X) { // do something } else if(list.items[n].e == MyEnum.VAL_Y) { // do something } }
替换为:
int valX = MyEnum.VAL_X.ordinal(); int valY = MyEnum.VAL_Y.ordinal(); int count = list.size(); MyItem items = list.items(); for(int n =0; n < count; n++) { intvalItem = items[n].e.ordinal(); if(valItem == valX) { // do something } else if(valItem == valY) { // do something } }
会使性能得到一些改善,但这并不是最终的解决之道。