对写出高效率的代码有很大的帮助
这里比较一下ArrayList和LinkedList:
1.ArrayList是基于数组,LinkedList基于链表实现。
2.对于随机访问get和set,ArrayList觉得优于LinkedList,因为LinkedList要移动指针。
3.对于新增和删除操作add和remove,LinedList比较占优势,因为ArrayList要移动数据。
4.查找操作indexOf,lastIndexOf,contains等,两者差不多。
这里只是理论上分析,事实上也不一定,比如ArrayList在末尾插入和删除数据就不设计到数据移动,不过还是
有这么个建议:随机访问比较多的话一定要用ArrayList而不是LinkedList,如果需要频繁的插入和删除应该
考虑用LinkedList来提高性能。
multiple dimension array
Java里面的multiple dimension array实际上是用array of arrays来模拟的,这样导致他们可能并非储存在连续的内存空间,会引起比较糟糕的内存访问的问题。
IBM的ninja group开发了一个package来解决这个问题,Array Package
减少不必要的对象的创建是提高性能的好办法。
不仅对JAVA,所有语言都适用。
避免在循环条件中使用复杂表达式 在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。
为'Vectors' 和 'Hashtables'定义初始大小 JVM为Vector扩充大小的时候需要重新创建一个更大的数组,将原原先数组中的内容复制过来,最后,原先的数组再被回收。可见Vector容量的扩大 是一个颇费时间的事。通常,默认的10个元素大小是不够的。你最好能准确的估计你所需要的最佳大小
在finally块中关闭Stream 程序中使用到的资源应当被释放,以避免资源泄漏。这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。
使用'System.arraycopy ()'代替通过来循环复制数组
'System.arraycopy ()' 要比通过循环来复制数组快的多。
在一些知道循环次数的循环中使用short甚至byte.
好象很多人习惯用int
字符串的连接尽可能使用stringbuffer
ava.lang.StringBuffer线程安全的可变字符序列。一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。
可将字符串缓冲区安全地用于多个线程。可以在必要时对这些方法进行同步,因此任意特定实例上的所有操作就好像是以串行顺序发生的,该顺序与所涉及的每个线程进行的方法调用顺序一致。
StringBuffer 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串缓冲区中。 append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容是“start”的字符串缓冲区对象,则此方法调用 z.append("le") 会使字符串缓冲区包含“startle”,而 z.insert(4, "le") 将更改字符串缓冲区,使之包含“starlet”。
通常,如果 sb 引用 StringBuilder 的一个实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。
只要发生有关源序列(如在源序列中追加或插入)的操作,该类就只在执行此操作的字符串缓冲区上而不是在源上实现同步。
每 个字符串缓冲区都有一定的容量。只要字符串缓冲区所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区数组。如果内部缓冲区溢出,则此容量自 动增大。从 JDK 5 开始,为该类补充了一个单个线程使用的等价类,即 StringBuilder。与该类相比,通常应该优先使用 StringBuilder 类,因为它支持所有相同的操作,但由于它不执行同步,所以速度更快。
java.lang.StringBuilder 一个可变的字符序列。此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。
在 StringBuilder 上的主要操作是 append 和 insert 方法,可重载这些方法,以接受任意类型的数据。每个方法都能有效地将给定的数据转换成字符串,然后将该字符串的字符追加或插入到字符串生成器中。 append 方法始终将这些字符添加到生成器的末端;而 insert 方法则在指定的点添加字符。
例如,如果 z 引用一个当前内容为“start”的字符串生成器对象,则该方法调用 z.append("le") 将使字符串生成器包含“startle”,而 z.insert(4, "le") 将更改字符串生成器,使之包含“starlet”。
通 常,如果 sb 引用 StringBuilder 的实例,则 sb.append(x) 和 sb.insert(sb.length(), x) 具有相同的效果。 每个字符串生成器都有一定的容量。只要字符串生成器所包含的字符序列的长度没有超出此容量,就无需分配新的内部缓冲区。如果内部缓冲区溢出,则此容量自动 增大。
将 StringBuilder 的实例用于多个线程是不安全的。如果需要这样的同步,则建议使用 StringBuffer。
使类和成员的可访问能力最小化
复合优先于继承
接口优先于抽象类
如果字符串特别长,采用charAt逐一获取特定位置的字符是非常耗时的。因为每次获取制定索引位置的字符都要引起新的检索过程,更好的办法是将字符串通过调用toCharArray方法转换成字符数组,然后通过数组索引值获得指定位置的字符
使用移位操作来代替'a / b'操作 "/"是一个很“昂贵”的操作,使用移位操作将会更快更有效。
对于boolean值,避免不必要的等式判断 将一个boolean值与一个true比较是一个恒等操作(直接返回该boolean变量的值). 移走对于boolean的不必要操作至少会带来2个好处: 1)代码执行的更快 (生成的字节码少了5个字节); 2)代码也会更加干净
尽量不要将大对象放到HttpSession或其他须序列化的对象中,并注意及时清空Session
引用《代码大全》的一句话:
我得到了一个教训,如果没有测量性能变化,那么你想当然的优化结果不过是代码变得更为晦涩难懂了。如果你认为没有必要通过测量来证实哪种方法更为有效,那么同样也没有必要牺牲代码可读性,而把赌注押在性能的提高上。
不应该为想当然的性能改进而采用更晦涩的做法。
比如14楼的“使用移位操作来代替'a / b'操作 "/"是一个很“昂贵”的操作,使用移位操作将会更快更有效。”
首先是性能究竟损失了多少?
性能是不是在可以接受的范围内?
更何况采用了想象的高性能方法,但最终的性能提升却几乎可以忽略不计。
对上面的操作我做了一下试验:在10万次运算中,可以转化为移位操作的整数除运算耗时16毫秒。。有必要为此做代码优化吗?
代码1:运行时间16毫秒
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
long n = start / 2;
}
System.out.println(System.currentTimeMillis() - start);
代码2:运行时间0
long start = System.currentTimeMillis();
for (int i = 0; i < 100000; i++) {
long n = start >> 1;
}
System.out.println(System.currentTimeMillis() - start);
java中有很一些类是为同步而设置的。比如Hashtable,为了防止多个用户同时访问时出现问题进行了一些很好的设计。如果,你的数据可以被多个人 访问,但是是一次写入,然后基本上值有读的操作,那就可以考虑不用它的同步机制,而是用HashMap等来代替它。而自己在适当的地方做些控制。(不是特 别推荐)
String / StringBuffer /StringBuilder,在字符串连接操作上性能依次加强,我曾经做过一个实验,连续进行10000次的字符串操作,三者速度上的差距是惊人的。在 确切知道是不变字符串的情况下,还是用String最好,因为Java语言中String采用了享元模式(Flyweight),在JVM中只存在一份相 同的String
用++i,代替i++