1、
For循环的优化
Replace...
for( int i = 0; i < collection.size(); i++ ) {
...
}
with...
for( int i = 0,int n = collection.size(); i < n; i++ ) {
...
}
2、 字符串操作优化
在对字符串实行+操作时,最好用一条语句
// Your source code looks like...
String str = "profit = revenue( " + revenue +
") - cost( " + cost + ")";
// 编译方法
String str = new StringBuffer( ).append( "profit = revenue( " ).
append( revenue ).append( ") - cost( " ).
append( cost ).append( ")" ).toString( );
在循环中对字符串操作时改用StringBuffer.append()方法
String sentence = "";
for( int i = 0; i < wordArray.length; i++ ) {
sentence += wordArray[ i ];
}
优化为
StringBuffer buffer = new StringBuffer( 500 );
for( int i = 0,int n=wordArray.length; i <n ; i++ ) {
buffer.append( wordArray[ i ] );
}
String sentence = buffer.toString( );
StringBuffer类可以用StringBuilder来代替
StringBuffer 和StringBuilder的区别:
java.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。StringBuilder。与该类相比,通常应该优先使用 java.lang.StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。为了获得更好的性能,在构造 StirngBuffer 或 StirngBuilder 时应尽可能指定它的容量。当然,如果你操作的字符串长度不超过 16 个字符就不用了。 相同情况下使用 StirngBuilder 相比使用 StringBuffer 仅能获得 10%-15% 左右的性能提升,但却要冒多线程不安全的风险。而在现实的模块化编程中,负责某一模块的程序员不一定能清晰地判断该模块是否会放入多线程的环境中运行,因 此:除非你能确定你的系统的瓶颈是在 StringBuffer 上,并且确定你的模块不会运行在多线程模式下,否则还是用 StringBuffer 吧。
StringBuffer表示了可变的、可写的字符串。
有三个构造方法 :
StringBuffer (); //默认分配16个字符的空间
StringBuffer (int size); //分配size个字符的空间
StringBuffer (String str); //分配16个字符+str.length()个字符空间
你可以通过StringBuffer的构造函数来设定它的初 始化容量,这样可以明显地提升性能。这里提到的构造函数是StringBuffer(int length),length参数表示当前的StringBuffer能保持的字符数量。你也可以使用ensureCapacity(int minimumcapacity)方法在StringBuffer对象创建之后设置它的容量。首先我们看看StringBuffer的缺省行为,然后再找 出一条更好的提升性能的途径。
StringBuffer在内部维护一个字符数组,当你使用缺省的构造函数来创建StringBuffer对象 的时候,因为没有设置初始化字符长度,StringBuffer的容量被初始化为16个字符,也就是说缺省容量就是16个字符。当 StringBuffer达到最大容量的时候,它会将自身容量增加到当前的2倍再加2,也就是(2*旧值+2)。如果你使用缺省值,初始化之后接着往里面 追加字符,在你追加到第16个字符的时候它会将容量增加到34(2*16+2),当追加到34个字符的时候就会将容量增加到70(2*34+2)。无论何 事只要StringBuffer到达它的最大容量它就不得不创建一个新的字符数组然后重新将旧字符和新字符都拷贝一遍――这也太昂贵了点。所以总是给 StringBuffer设置一个合理的初始化容量值是错不了的,这样会带来立竿见影的性能增益。
StringBuffer初始化过程的调整的作用由此可见一斑。所以,使用一个合适的容量值来初始化StringBuffer永远都是一个最佳的建议。
3、关于乘法与除法
我有太多的东东适用于摩尔法则——它声明CPU功率每年成倍增长。"摩尔法则"表明每年由开发者所写的差劲的代码数量三倍增加,划去了摩尔法则的任何好处。
考虑下面的代码:
for (val = 0; val < 100000; val +=5) { shiftX = val * 8; myRaise = val * 2; }
如果我们狡猾的利用位移(bit),性能将会六倍增加。这是重写的代码:
for (val = 0; val < 100000; val += 5) { shiftX = val << 3; myRaise = val << 1; }
代替了乘以8,我们使用同等效果的左移3位。每一个移动相当于乘以2,变量myRaise对此做了证明。同样向右移位相当于除以2,当然这会使执行速度加快,但可能会使你的东东以后难于理解;所以这只是个建议,,若用最好加上一些注释。
4、
array(数组) 和 ArryList的使用
array([]):最高效;但是其容量固定且无法动态改变;
ArrayList:容量可动态增长;但牺牲效率;
基于效率和类型检验,应尽可能使用array,无法确定数组大小时才使用ArrayList!
ArrayList是Array的复杂版本
ArrayList内部封装了一个Object类型的数组,从一般的意义来说,它和数组没有本质的差别,甚至于ArrayList的许多方法,如Index、IndexOf、Contains、Sort等都是在内部数组的基础上直接调用Array的对应方法。
ArrayList存入对象时,抛弃类型信息,所有对象屏蔽为Object,编译时不检查类型,但是运行时会报错。
注:jdk5中加入了对泛型的支持,已经可以在使用ArrayList时进行类型检查。
从这一点上看来,ArrayList与数组的区别主要就是由于动态增容的效率问题了
5、
不用new关键词创建类的实例
用new关键词创建类的实例时,构造函数链中的所有构造函数都会被自动调用。但如果一个对象实现了Cloneable接口,我们可以调用它的clone()方法。clone()方法不会调用任何类构造函数。
在使用设计模式(Design Pattern)的场合,如果用Factory模式创建对象,则改用clone()方法创建新的对象实例非常简单。例如,下面是Factory模式的一个典型实现:
上面的思路对于数组处理同样很有用。
- public static Credit getNewCredit() {
- return new Credit();
- }
- 改进后的代码使用clone()方法,如下所示:
- private static Credit BaseCredit = new Credit();
- public static Credit getNewCredit() {
- return (Credit) BaseCredit.clone();
- }
6、代码重构:增强代码的可读性。
例如:
- public class ShopCart {
- private List carts ;
- …
- public void add (Object item) {
- if(carts == null) {
- carts = new ArrayList();
- }
- crts.add(item);
- }
- public void remove(Object item) {
- if(carts. contains(item)) {
- carts.remove(item);
- }
- }
- public List getCarts() {
- //返回只读列表
- return Collections.unmodifiableList(carts);
- }
- //不推荐这种方式
- //this.getCarts().add(item);
- }
7、
当复制大量数据时,使用System.arraycopy()命令。
System提供了一个静态方法arraycopy(),我们可以使用它来实现数组之间的复制。其函数原型是:
public static void arraycopy(Object src, int srcPos, Object dest, int destPos, int length)
src:源数组; srcPos:源数组要复制的起始位置;
dest:目的数组; destPos:目的数组放置的起始位置; length:复制的长度。
注意:src and dest都必须是同类型或者可以进行转换类型的数组.
有趣的是这个函数可以实现自己到自己复制,比如:
int[] fun ={0,1,2,3,4,5,6};
System.arraycopy(fun,0,fun,3,3);
则结果为:{0,1,2,0,1,2,6};
实现过程是这样的,先生成一个长度为length的临时数组,将fun数组中srcPos
到srcPos+length-1之间的数据拷贝到临时数组中,再执行System.arraycopy(临时数组,0,fun,3,3).