java代码优化

Java开源代码优化分类列表

 

http://www.open-open.com/45.htm

 

java代码优化

 

url: http://dannybai.javaeye.com/blog/542721

 

原文讨论:http://java-xiaodi.javaeye.com/blog/142359

 

每一种语言都有其自身的特点,只有掌握了其自身的特点,才能用它编写出高效的程序。下面就我个人实践所知谈谈javaSE方面的性能问题,
javaEE方面的性能暂不讨论,要是时间可以再写一javaEE方面的性能问题的帖子。

1, 尽量不要使用+号来连接字符串,至少不要在隔行中使用+来连接字符串。因为有的java虚拟机可能对字符串连接+做了性能优化,在都同行的+字符串连接,转化为StringBuffer的append()方法来连接,所以在同行使用+和使用StringBuffer的append 来做连接性能上差不多。

2, 对小数据int的Integer封装,尽量的使用Integer.valueOf()创建,而不要使用new来创建。因为Integer类缓存了从-128到256个 状态的Integer。

3, 对Boolean类,要用valueOf()或使用Boolean.TRUE或Boolean.FALSE来创建对象。我个人觉得对Boolean类用private构造函数,可能就会避免不好的使用Boolean类了。

4, 在设计类时应尽可能地避免在类的默认构造函数中创建,初始化大量的对象

5, 合理的申请数组空间,如果数组中所保存的元素占用内存空间较大或数组本身长度较长的情况,我们釆用可以釆用软引用的技术来引用数组,以“提醒”JVM及时的回收垃圾内存,维护系统的稳定性。

6,  避免创建重复的对象,我们在编写一个方法的时候应该先考虑方法里的局部对象域能否改为private static final,从而避免创建重复的对象

7, 把try/catch块放入循环体内,会极大的影响性能,如果编译JIT被关闭或者你所使用的一个不带JIT的JVM,性能会将下降21%之多!

8,StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建StringBuffer的时候指定大小,这样就避免了在容量不够的时候自动增长,以提高性能

9, 使用Java NIO提高服务端程序的性能。

10,考虑用静态工厂方法替代构造函数

11,在对大量的数组拷贝时,可以考虑用Arrays.copyOf()来拷贝

12, 在并发的情况下,要合理的选择同步的策略,应该谨慎的控制synchronized块的大小,不可以将一个操作分解到多个synchronized 但也要尽量地从synchronized块中分离耗时的且不影响并发的操作。

13,要合理的选择集合框架,例如:ArrayList和LinkedList在某些不同的场合,其性能相差很大。对要做大量的插入时, LinkedList 的性能比ArrayList的性能好。对要做大量随机查找的时候用ArrayList的性能比用LinkedList的性能好。还有在不需要并发操作的情况下,选择非线程安全的集合比线程安全的集合要好。如在非线程安全的要求下,选择ArrayList要比Vector好。

14,不要在循环语句块中调用length()方法做为循环结束的条件

15,如果字符串特别长,不要釆用charAt()一一的获取特定位置的字符,而应该调用toCharArray()方法转化为字符数组,然后通过数组 索引值获取指定位置的字符。

16,如果是想把数据封装成Double类型的,不要这样使用new Double("1.23"),而要应这样使用new Double(1.23),虽然二者都没有语法 的错误,也都能达到预期的结果,但其性能有着很大的差异。

17, 应尽量的通过缓冲流类来提高I/O操作效率,但也要合理的选择缓冲大小 。

 

 

 

 

=======================================================

Java代码优化策略

 

url:http://nakata-yf.javaeye.com/blog/23545

 

整理了一些影响性能的代码和优化方法,以后希望能陆续补充和优化

1. 如何使用Exception
Exception降低性能。一个异常抛出首先需要创建一个新的对象。Throwable接口中的构造器调用名为fillInStackTrace()的本地方法。这个方法负责巡检栈的整个框架来收集跟踪信息。这样无论何时有异常抛出,它要求虚拟机装载调用栈,因为一个新的对象在中部被创建
异常应当仅用于有错误发生时,而不要控制流。


2. 不要两次初始化变量
Java通过调用独特的类构造器默认地初始化变量为一个已知的值。所有的对象被设置成null,integers (byte, short, int, long)被设置成0,float和double设置成0.0,Boolean变量设置成false。这对那些扩展自其它类的类尤其重要,这跟使用一个新的关键词创建一个对象时所有一连串的构造器被自动调用一样。


3. 在任何可能的地方让类为Final
标记为final的类不能被扩展。在《核心Java API》中有大量这个技术的例子,诸如java.lang.String。将String类标记为final阻止了开发者创建他们自己实现的长度方法。
更深入点说,如果类是final的,所有类的方法也是final的。Java编译器可能会内联所有的方法(这依赖于编译器的实现)。在我的测试里,我已经看到性能平均增加了50%。


4. 在任何可能的地方使用局部变量
属于方法调用部分的自变量和声明为此调用一部分的临时变量存储在栈中,这比较快。诸如static,实例(instance)变量和新的对象创建在堆中,这比较慢。局部变量的更深入优化依赖于你正在使用的编译器或虚拟机。


5. 停止小聪明
很多开发人员在脑子中编写可复用和灵活的代码,而有时候在他们的程序中就产生额外的开销。曾经或者另外的时候他们编写了类似这样的代码:
public void doSomething(File file) {
FileInputStream fileIn = new FileInputStream(file);
// do something
他够灵活,但是同时他们也产生了更多的开销。这个主意背后做的事情是操纵一个InputStream,而不是一个文件,因此它应该重写如下:
public void doSomething(InputStream inputStream){
// do something


6. 乘法和除法
我有太多的东东适用于摩尔法则——它声明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,当然这会使执行速度加快,但可能会使你的东东以后难于理解;所以这只是个建议


7. 用代码有效处理内存溢出
OutOfMemoryError是由于内存不够后普遍会遇到的问题,下面一段代码能有效判断内存溢出错误,并在内存溢出发生时有效回收内存
通过该方法可以联想到有效管理连接池溢出,道理等同。
import java.util.*;
public class DataServer
{

private Hashtable data = new Hashtable();
public Object get (String key)
{

Object obj = data.get (key);
if (obj == null)
{

System.out.print (key + “ ”);
try
{

// simulate getting lots of data
obj = new Double[1000000];
data.put (key, obj);
}

catch (OutOfMemoryError e)
{

System.out.print (“/No Memory! ”);
flushCache();
obj = get (key);// try again
}

}
return (obj);
}

public void flushCache()
{

System.out.println (“Clearing cache”);
data.clear();
}

public static void main (String[] args)
{

DataServer ds = new DataServer();
int count = 0;
while (true) // infinite loop for test
ds.get (“” count+);
}

}


8. Lazy Loading (Lazy evaluation)在需要装入的时候才装入
static public long
factorial( int n ) throws IllegalArgumentException
{

IllegalArgumentException illegalArgumentException =
new IllegalArgumentException( “must be >= 0” );
if( n < 0 ) {
throw illegalArgumentException ;
} else if( ( n 0 ) || ( n 1 ) ) {
return( 1 );
} else (
return( n * factorial( n – 1 ) ) ;
}

优化后代码
static public long
factorial( int n ) throws IllegalArgumentException
{

if( n < 0 ) {
throw new IllegalArgumentException( “must be >= 0” );
} else if( ( n 0 ) || ( n 1 ) ) {
return( 1 );
} else (
return( n * factorial( n – 1 ) ) ;
}

9. 异常在需要抛出的地方抛出,try catch能整合就整合
try {
some.method1(); // Difficult for javac
} catch( method1Exception e ) { // and the JVM runtime
// Handle exception 1 // to optimize this
} // code
try {
some.method2();
} catch( method2Exception e ) {
// Handle exception 2
}

try {
some.method3();
} catch( method3Exception e ) {
// Handle exception 3
}

已下代码 更容易被编译器优化
try {
some.method1(); // Easier to optimize
some.method2();
some.method3();
} catch( method1Exception e ) {
// Handle exception 1
} catch( method2Exception e ) {
// Handle exception 2
} catch( method3Exception e ) {
// Handle exception 3
}

10. For循环的优化
Replace…
for( int i = 0; i < collection.size(); i++ ) {
...
}

with…
for( int i = 0, n = collection.size(); i < n; i++ ) {
...
}

11. 字符串操作优化
在对字符串实行+操作时,最好用一条语句
// 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; i < wordArray.length; i++ ) {
buffer.append( wordArray[ i ] );
}

String sentence = buffer.toString( );


12. 对象重用(特别对于大对象来说)
public
class Point
{

public int x;
public int y;
public Point( )
{

this( 0, 0 );
}

}
优化为:
public class Component
{

private int x;
private int y;
public Point getPosition( )
{

Point rv = new Point( ); // Create a new Point
rv.x = x; // Update its state
rv.y = y;
return rv;
}

}
// Process an array of Component positions…
for( int i = 0; i < componentArray.length; i++ ) {
Point position = componentArray[i].getPosition( );
// Process position value…
// Note: A Point object is created for each iteration
// of the loop…
}

可再次优化,仅使用一个类对象:)
public
class Component
{

private int x;
private int y;
public Point getPosition( Point rv )
{

if( rv == null) rv = new Point( );
rv.x = x; // Update its state
rv.y = y;
return rv;
}

// Create a single point object and reuse it…
Point p = new Point( );
for( int i = 0; i < componentArray.length; i++ ) {
Point position = componentArray[i].getPosition( p );
// Process position value…
// Note: Only one Point object is ever created.
}

13. j2ee相关
a) 尽量不要将大对象放到HttpSession或其他须序列化的对象中,并注意及时清空Session
b) 使用预编译语句prepareStatement代替createStatement
c) 尽可能使用连接池
d) 能使用Cache就使用Cache,具体实现可参考jive(Cache/Cacheable/CacheObject/CacheSizes/DefaultCache/LinkdList/LinkdListNode)或ofbiz(org.ofbiz.core.util. UtilCache.java)

 

 

 

Java代码优化方案 J2ME内存优化

url:http://www.cnblogs.com/yangyh/archive/2009/08/13/1544819.html
从几本书上,N个网站上整理的一些JAVA代码优化方案,最近的项目只有1M内存可用,必须很抠门了~J2ME项目更要注意的
避免内存溢出

l 不用的对象释放(置空)

如 :

a不为空时 a=new object()//这句代码执行时将有两个对象存在于内存中

较好的写法是a=null; a=new object();

不用的对象设置成null

l 内存溢出通常发生在构造函数中,在构造函数中变量在要用时再new,用完之后置null

一次性加载所有图片很容易造成内存峰值。

可以用 if(img==null){

Create…

}

l 考虑用静态工厂方法替代构造函数(但是,注意释放,单例模式的释放只能由自己来做)。

l 使用局部变量

l 图形重绘操作用部分重绘

l 避免在同一个类中通过调用get set来设置或调用变量,用public

l 避免在循环中生成同一个变量或调用同一个函数

l 常用变量尽可能用static final private

l 能用byte的就不用int,String

l 不要使用double

l 复制大量数据时用System.appaycopy()

l 避免使用泛型

l 尽量不使用try catch,必须使用时不要在循环体内写try catch

l 字符串操作使用StringBuffer

代码2是代码1执行速度的两倍:

代码1:

String title=new String(“大家好”);

Title+=”欢迎”;

Title+=”阅读”

//会在栈中生成五个对象:“大家好”,“欢迎”,“阅读”,“大家好欢迎”,“大家好欢迎阅读”

代码2:

StringBuffer title=new StringBuffer(“大家好”);

Tltle.append(“欢迎”);

Title.append(“阅读”);

l StringBuffer的构造器会创建一个默认大小(通常是16)的字符数组。在使用中,如果超出这个大小,就会重新分配内存,创建一个更大的数组,并将原先的数组复制过来,再丢弃旧的数组。在大多数情况下,你可以在创建StringBuffer的时候指定大小,这就避免了在容量不够的时候自动增长,以提高性能。

l 使用零值做为判断条件

For(int i=a.length()-1;i>=0;i--) 优于 for(int i=0;i<a.length();i++)

l 不要重复初始化变量

默认情况下,调用类的构造函数时, Java会把变量初始化成确定的值:所有的对象被设置成null,整数变量(byte、short、int、long)设置成0,float和 double变成0.0,逻辑值设置成false

l 乘法和除法用移位 ,除法比乘法慢,所以用乘于倒数来代替除法

考虑下面的代码:

for (val = 0; val < 100000; val +=5) { alterX = val * 8; myResult = val * 2; }

用移位操作替代乘法操作可以极大地提高性能。下面是修改后的代码:

for (val = 0; val < 100000; val += 5) { alterX = val << 3; myResult = val << 1; }

l 传递尽可能少的参数到经常调用的方法

l 不要有空方法,或方法内代码很少而方法又很少调用

l 避免类型转换

使用Profiler去查找哪里需要优化

改进你的算法,写最优的代码
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值