目录
1. 尽量使用final修饰符
2.. 尽量减少对变量的重复计算
3.. 尽量避免不必要的创建
4. 尽量使用移位来代替’a/b’和’a*b’的操作
5. 尽量确定StringBuffer的容量
6. 尽量避免使用二维数组
7. 尽量避免使用split
8. ArrayList (线性表)& LinkedList(链表)
9. 慎用异常
10. SQL语言应尽量使用大写形式
11. 不要在循环中使用Try/Catch语句,应把Try/Catch放在循环最外层
12. array(数组)和ArrayList的使用
1. 尽量使用final修饰符
带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java、lang、String,为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关),此举能够使性能平均提高50%。
如:让访问实例内变量的getter/setter方法变成”final:
简单的getter/setter方法应该被置成final,这会告诉编译器,这个方法不会被重载,所以,可以变成”inlined”,例子
public class Student {
private String name;
private Integer age;
//普通使用
final public String getName() {
return name;
}
final public Integer getAge() {
return age;
}
//优化使用
public String getName() {
return name;
}
public Integer getAge() {
return age;
}
}
2.. 尽量减少对变量的重复计算
如:
for(int i=0;i<list.size();i++)
- 上面的每次循环都要交计算list.size(),下面的将list.size()首先计算出来放入变量len,避免了多次重复计算
应该改为:
for(int i=0,len=list.size();i<len;i++)
并且在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。
3.. 尽量避免不必要的创建
如:
A a = new A();
if(i==1){
list.add(a);
}
//应该改为下面的代码,因为上面的是先创建对象,然后再判断是否添加,如果不符合if条件,那么对象也会被创建影响性能
if(i==1){
A a = new A();
list.add(a);
}
4. 尽量使用移位来代替’a/b’和’a*b’的操作
“/”和‘*’是一个代价很高的操作,使用移位的操作将会更快和更有效
如:
int num = a / 4;
int num = a / 8;
//应该改为
int num = a >> 2;
int num = a >> 3;
int num = a * 4;
int num = a * 8;
//应该改为
int num = a << 2;
int num = a << 3;
5. 尽量确定StringBuffer的容量
StringBuffer 的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建 StringBuffer的时候指定合适的大小,这样就避免了在容量不够的时候自动增长,以提高性能。无论何时,只要StringBuffer到达它的最大容量,它就不得不创建一个新的对象数组,然后复制旧的对象数组,这会浪费很多时间。所以给StringBuffer设置一个合理的初始化容量值,是很有必要的!
如:
StringBuffer buffer = new StringBuffer(1000);
StringBuffer初始化时,其容量大小(Capacity)为16;其后容量不够时按照9*(2的n次方)来增长。
当对字符串进行修改的时候,需要使用 StringBuffer 和 StringBuilder 类。
和 String 类不同的是,StringBuffer 和 StringBuilder 类的对象能够被多次的修改,并且不产生新的未使用对象。
StringBuilder 类在 Java 5 中被提出,它和 StringBuffer 之间的最大不同在于 StringBuilder 的方法不是线程安全的(不能同步访问)。
由于 StringBuilder 相较于 StringBuffer 有速度优势,所以多数情况下建议使用 StringBuilder 类。然而在应用程序要求线程安全的情况下,则必须使用 StringBuffer 类。 相同情况下,使用StringBuilder比使用StringBuffer仅能获得10%~15%的性能提升,但却要冒多线程不安全的风险。综合考虑还是建议使用StringBuffer。
public static void main(String[] args) {
StringBuffer buffer= new StringBuffer(100);
buffer.append(66);
buffer.append("我是学生");
System.out.println(buffer);
StringBuilder builder=new StringBuilder(100);
/**
* public StringBuffer append(String s)
* 将指定的字符串追加到此字符序列。
*/
builder.append(12);
builder.append("我是学生1");
builder.append("我是学生2");
builder.append("我是学生3");
System.out.println(builder);
/**
* public delete(int start, int end),
* start:开始的字符串的位置,从0开始,end:结束的字符串的位置
*/
builder.delete(0,3);
/**
* public insert(int offset, object i)
* 将参数i的字符串表示形式插入此序列中。
* offset:从什么位置开始插入
*/
int i =12;
builder.insert(0,i);
System.out.println(builder);
/**
* int length()
* 返回长度(字符数),中文和英文都算一个字符
*/
System.out.println(builder.length());
/**
*String toString()
*返回此序列中数据的字符串表示形式。
*/
builder.toString().split("");
}
6. 尽量避免使用二维数组
二维数据占用的内存空间比一维数组多得多,大概10倍以上。
7. 尽量避免使用split
除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。
8. ArrayList (线性表)& LinkedList(链表)
一个是线性表,一个是链表,一句话,随机查询尽量使用ArrayList,ArrayList优于LinkedList,LinkedList还要移动指针,添加删除的操作LinkedList优于ArrayList,ArrayList还要移动数据
9. 慎用异常
当创建一个异常时,需要收集一个栈跟踪(stack track),这个栈跟踪用于描述异常是在何处创建的。构建这些栈跟踪时需要为运行时栈做一份快照,正是这一部分开销很大。当需要创建一个 Exception 时,JVM 不得不说:先别动,我想就您现在的样子存一份快照,所以暂时停止入栈和出栈操作。栈跟踪不只包含运行时栈中的一两个元素,而是包含这个栈中的每一个元素。
如果您创建一个 Exception ,就得付出代价,好在捕获异常开销不大,因此可以使用 try-catch 将核心内容包起来。从技术上讲,你甚至可以随意地抛出异常,而不用花费很大的代价。招致性能损失的并不是 throw 操作——尽管在没有预先创建异常的情况下就抛出异常是有点不寻常。真正要花代价的是创建异常,不应该不管三七二十一就抛出异常。异常是为异常的情况而设计的,使用时也应该牢记这一原则
10. SQL语言应尽量使用大写形式
在java+Oracle的应用系统开发中,java中内嵌的SQL语言应尽量使用大写形式,以减少Oracle解析器的解析负担。
11. 不要在循环中使用Try/Catch语句,应把Try/Catch放在循环最外层
12. array(数组)和ArrayList的使用
array 数组效率最高,但容量固定,无法动态改变,ArrayList容量可以动态增长,但牺牲了效率。
为什么一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
那么为什么不List list; list=null; list.add(123);?因为list是接口这样使用时错误的
方便以后扩展
List是一个接口,而ArrayList 是一个类。 ArrayList 继承并实现了List。
List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。而ArrayList list=new ArrayList();创建一对象则保留了ArrayList的所有属性。
为什么一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢?
问题就在于List有多个实现类,如 LinkedList或者Vector等等,现在你用的是ArrayList,也许哪一天你需要换成其它的实现类呢?,这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。假设你开始用 ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了 ArrayList特有的方法和属性。 如果没有特别需求的话,最好使用List list = new LinkedList(); ,便于程序代码的重构. 这就是面向接口编程的好处。