`
hy2012_campus
  • 浏览: 30582 次
  • 性别: Icon_minigender_1
  • 来自: 河南
社区版块
存档分类
最新评论

java代码优化

    博客分类:
  • java
 
阅读更多

来源于:http://thecodesample.com/

本文给出几个提升Java性能的基本方法:

不要在循环条件中计算

如果在循环 (如for循环、while循环)条件中计算,则循环一遍就要计算一次,这会降低系统的效率,如:

//每次循环都要计算 count *2
while(i < count *2) {
    //Do something ...
}
应该替换为:
//只计算一遍
int total = count *2
while(i <total) {
    //Do something ...
}
再如:
for (int i=0; i<size()*2; i++) {
    //Do something
}
应该改成:
for (int i=0, stop=size()*2; i<stop; i++) {
    //Do something
}

 不要将相同的子表达式计算多次

if (birds.elementAt(i).isGrower()) ...
if (birds.elementAt(i).isPullet()) ...
将相同的子表达式提取为一个变量,如:
Bird bird = birds.elementAt(i);
if (bird.isGrower()) ...
if (bird.isPullet()) ...

 

减少数组访问次数,每次数组访问都需要检查一下索引,所以减少数组访问的次数是值得的。
double[] rowsum = new double[n];
for (int i = 0; i < n; i++)
    for (int j = 0; j < m; j++)
        rowsum[i] += arr[i][j];
改成如下形式:
double[] rowsum = new double[n];
for (int i = 0; i < n; i++) {
    double[] arri = arr[i];
    double sum = 0.0;
    for (int j = 0; j < m; j++)
        sum += arri[j];
    rowsum[i] = sum;
}

 尽可能把变量、方法声明为 final static 类型

如下例子用于返回给定年份给定月份所具有的天数。

public static int monthdays(int y, int m) {
    int[] monthlengths = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
    
    return m == 2 && leapyear(y) ? 29 : monthlengths[m-1];
}

 上述方法每次调用都会重新生成一个monthlengths 数组,但必要要主要的是:数组不会改变,属于不变数组。在这种情况下,

把它声明为 final static 更加合适,在类加载后就生成该数组,每次方法调用则不再重新生成数组对象了,这有助于提高系统性能。

应该改成:
private final static int[] monthlengths = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31 };
public static int monthdays(int y, int m) {
    return m == 2 && leapyear(y) ? 29 : monthlengths[m-1];
}
稍微复杂一些的初始化可以使用静态初始化块static {… }来做,如:
private final static double[] logFac = new double[100];
static {
    double logRes = 0.0;
    for (int i=1, stop=logFac.length; i<stop; i++)
        logFac[i] = logRes += Math.log(i);
}
 
public static double logBinom(int n, int k) {
    return logFac[n] - logFac[n-k] - logFac[k];
}

 缩小变量的作用范围

关于变量,能定义在方法内的就定义在方法内,能定义在一个循环体内的就定义在循环体内,能放置在一个try…catch块内的就放置在该块内,

其目的是加快GC的回收。

 

字符串频繁”+”操作使用StringBuilder或者StringBuffer

 

虽然String的联接操作(“+”)已经做了很多优化,但大量的追加操作上StringBuilder或者StringBuffer还是比”+”的性能好很多。

String s = "";
for (int i=0; i<n; i++) {
    s += "#" + i;
}
应该改成:
StringBuilder sbuf = new StringBuilder();
for (int i=0; i<n; i++) {
    sbuf.append("#").append(i);
}
String s = sbuf.toString();
此外,
String s = "(" + x + ", " + y + ")";
它将自动会编译为StringBuilder.append(…)。

 覆写Exception的fillInStackTrace方法

fillInStackTrace方法是用来记录异常时的栈信息的,这是非常耗时的动作,如果在开发时不需要关注栈信息,则可以覆盖之,

如下覆盖fillInStackTrace的自定义异常会使性能提升10倍以上:

class MyException extends Exception {
   public Throwable fillInStackTrace() {
      return this;
   }
}

 延迟初始化

当你不知道一个对象是否需要的时候,可以选择延迟初始化:直到需要的时候才初始化,但只分配一次。

public class Car {
    private Button button = new JButton();
    public Car() {
        ... initialize button ...
    }
    public final JButton getButton() {
        return button;
    }
}
可以改为:
public class Car {
    private Button button = null;
 
    public Car() { ... }
    public final JButton getButton() {
        if (button == null) { // button not yet created, so create it
            button = new JButton();
            ... initialize button ...
        }
        return button;
    }
}

 不要重复创建对象

比如,一个商品相关信息的更新,为了搜索,需要为其创建索引。

针对单个商品建立的索引如下:

public void index(Product product) {
    if (product != null) {
        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
        fullTextEntityManager.index(product);
    }
}
针对多个商品建立索引,可能会写出如下的代码,写一个for循环,直接调用单个商品索引建立的方法。
public void indexAll(List<Product> products) {
    if (products != null) {
        for (Product product : products) {
            index(product);
        }
    }
}
这个方法比较直观,但是为每一个Product创建索引的时候,都会新创建一个FullTextEntityManager对象。其实我们只需要创建一次,代码如下:
public void indexAll(List<Product> products) {
    if (products != null) {
        FullTextEntityManager fullTextEntityManager = Search.getFullTextEntityManager(entityManager);
        for (Product product : products) {
            fullTextEntityManager.index(product);
        }
    }
}
使用Collections.emptyXXX方法代替创建空的ArrayList,HashSet等

下面给出一个获取一个指定分类以及其所有父类的规格的方法
public Set<Specification> getAllSpecifications(ProductCategory productCategory) {
    Set<Specification> specifications = new HashSet<Specification>();
    if (null != productCategory) {
        specifications.addAll(productCategory.getSpecifications());
        specifications.addAll(productCategory.getParentSpecifications());
    }
    return specifications;
}
该方法中,不管productCategory是否为空,都会新建一个空的Set集合,而每次创建的空Set也会是不同的对象。我们可以先判断商品分类是否为空
,如果是空,则调用Collections的emptySet()方法,该方法将返回一个常量的空集,并不需要重新创建新的空集对象。

 

代码如下:
public Set<Specification> getAllSpecifications(ProductCategory productCategory) {
    if(productCategory == null){
        return Collections.<Specification>emptySet();
    }
    Set<Specification> specifications = new HashSet<Specification>();
    specifications.addAll(productCategory.getSpecifications());
    specifications.addAll(productCategory.getParentSpecifications());
    return specifications;
}
去掉重复代码

下面的例子是根据一个指定分类,获取其子分类的方法, 分类结果以Map的形式返回,key为分类id,value为分类名称,这个主要用
于前台Ajax去构建分类的树形结构。如果指定的分类为null,则获取根分类。
public Map<Long, String> getSubCategoryTree(Long parentId) {
    Map<Long, String> categoryOptions = new HashMap<Long, String>();
    ProductCategory productCategory = productCategoryService.find(parentId);
    if (null == productCategory) {
        for (ProductCategory pc : productCategoryService.findRoots()) {
            categoryOptions.put(pc.getId(), pc.getName());
        }
    } else {
        for (ProductCategory pc : productCategory.getChildren()) {
            categoryOptions.put(pc.getId(), pc.getName());
        }
    }
    return categoryOptions;
}
在这个方法中,if-else语句中除了获取的集合 productCategoryService.findRoots()和 productCategory.getChildren()不同外,其余都是一样的。
我们完全可以将这个集合提取出来,代码块将不再包含if-else块,同时for循环也只需要一个。

帮助
public Map<Long, String> getSubCategoryTree(Long parentId) {
    Map<Long, String> categoryOptions = new HashMap<Long, String>();
    ProductCategory productCategory = productCategoryService.find(parentId);
    Collection<ProductCategory> productCategories = (productCategory == null) ? productCategoryService
            .findRoots() : productCategory.getChildren();
    for (ProductCategory pc : productCategories) {
        categoryOptions.put(pc.getId(), pc.getName());
    }
    return categoryOptions;
}

 

去掉不必要的else块
private int getAttributeValueId(String value) {
    if (StringUtils.isEmpty(value)) {
        return -1;
    } else {
        String[] values = value.split(ATTRIBUTE_ID_SEPARATOR);
        String id = values[values.length - 1];
        return Integer.parseInt(id);
    }
}
可以改成
private int getAttributeValueId(String value) {
    if (StringUtils.isEmpty(value)) {
        return -1;
    }
    String[] values = value.split(ATTRIBUTE_ID_SEPARATOR);
    String id = values[values.length - 1];
    return Integer.parseInt(id);
 
}

 在不需要再用时关闭连接资源

下面是一个简单的查询数据库的代码,执行完查询操作之后,判断连接资源是否为null,如不为null,则调用相应的close()方法关闭资源。

Statement stmt = null;
ResultSet rs = null;
Connection conn = getConnection();
try{
    stmt = conn.createStatement();
    rs = stmt.executeQuery(sqlQuery);
    progressResult(rs);
}catch(SQLException e){
    //forward to handler
}finally {
    if(rs !=null){
        rs.close();
    }
    if(stmt != null){
        stmt.close();
    }
    if(conn !=null){
        conn.close();
    }
}
在这个关闭的过程中,存在着风险,比如rs在调用close()方法时发生异常,则stmt和conn将不会关闭。

 为了能够使资源都得到释放,应改为:

Statement stmt = null;
ResultSet rs = null;
Connection conn = getConnection();
try{
    stmt = conn.createStatement();
    rs = stmt.executeQuery(sqlQuery);
    progressResult(rs);
}catch(SQLException e){
    //forward to handler
}finally {
     
    try{
        if(rs !=null){
            rs.close();
        }
    }catch(SQLException e){
        //forward to handler
    }finally{
        try{
            if(stmt !=null){
                stmt.close();
            }
        }catch(SQLException e){
            //forward to handler
        }finally{
            try{
                if(conn !=null){
                    conn.close();
                }
            }catch(SQLException e){
                //forward to handler
            }
        }
    }
 
}
如果使用的是JDK1.7后的版本, 也可以使用Java SE 7中支持的使用try-with-resource的方式。
try(   
	Connection conn = getConnection(); 
	Statement stmt = conn.createStatement();
	ResultSet rs = stmt.executeQuery(sqlQuery)){
    progressResult(rs);
}catch(SQLException e){
    //forward to handler
}

 

分享到:
评论

相关推荐

    JAVA代码优化工具

    Java代码优化是提升应用程序性能的关键步骤,尤其是在大型企业级应用或者高性能服务中。优化能够减少内存消耗,提高程序运行速度,降低CPU使用率,并改善整体的用户体验。在Java开发领域,有多种工具可以帮助开发者...

    java代码优化简介

    Java代码优化是对程序进行改进的过程,旨在提升程序的运行效率,减少资源的消耗。优化主要关注两个方面:减小代码体积和提高代码执行效率。在Java中,性能问题往往源于编程习惯而非语言本身。以下是一些针对Java代码...

    java代码优化大全

    ### Java代码优化技巧详解 #### 一、引言 在软件开发过程中,为了提升应用程序的性能,我们需要对Java代码进行优化。这是因为计算机系统的资源(如内存、CPU时间、网络带宽等)是有限的,而优化的目标就是使程序...

    java代码优化编程

    【Java代码优化编程】 在Java编程中,代码优化是一个关键环节,目的是使程序在有限的资源下更高效地运行。优化主要包括两个方面:减小代码体积和提高代码执行效率。以下是一些关于如何提高Java代码效率的具体策略:...

    JAVA代码优化.txt

    JAVA代码优化 JAVA代码优化 JAVA代码优化 JAVA代码优化 JAVA代码优化

    44条Java代码优化建议

    Java代码优化是一个持续的过程,它包含了许多细节和技巧,能够帮助开发者编写出更高效、更易于维护的代码。在这44条Java代码优化建议中,我们可以提炼出一些核心的知识点,为Java编程实践提供参考。 首先,关于为...

    Java代码优化....................

    java代码优化 个人感觉这写的不错. 值得学习!

    JAVA代码优化实用策略

    非常实用的java代码优化策略详解,从变量声明、初始化、字符串链接、异常处理、IO、数组等各个方面进行优化,非常有参考价值。

    Java代码优化细节总结

    代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但是,吃...

    java 代码重构优化 Java 代码优化 java设计优化

    以上就是关于Java代码重构、优化以及设计优化的一些关键点,这些知识不仅能提升代码质量,还能帮助开发者更好地应对项目中的各种挑战。通过深入学习《重构-改善既有代码的设计》这样的经典书籍,你可以进一步提升...

    java代码优化编程共11页.pdf.zip

    Java代码优化是提升软件性能和效率的关键步骤,尤其是在大型企业级应用中,高效的代码能够显著降低服务器资源消耗,提高用户体验。这份"java代码优化编程共11页.pdf.zip"压缩包很可能包含了一份详尽的Java代码优化...

    Java代码优化方法大全共5页.pdf.zip

    Java代码优化是提升应用程序性能的关键步骤,特别是在大型企业级应用或者高并发系统中,优化能够显著提高系统效率,减少资源消耗。"Java代码优化方法大全共5页.pdf"可能是一份详细介绍了Java代码优化核心策略的文档...

    java代码优化1.0版本.zip

    本压缩包"java代码优化1.0版本.zip"包含了一份详细的优化指南——"java代码优化1.0版本.md",以下是基于这个主题的Java代码优化相关知识点的详细阐述。 1. **基本语法优化** - **避免使用冗余代码**:删除无用的...

    java代码优化细节总结1.0版本.7z

    Java代码优化是提升程序性能、减少资源消耗的关键环节。这份"java代码优化细节总结1.0版本.7z"压缩包包含了一份详细的Java代码优化指南,适用于开发者在编写和优化Java程序时参考。以下是根据标题、描述以及压缩包内...

    java代码优化总结1.0版本.zip

    这份"java代码优化总结1.0版本.zip"资源可能包含了关于如何提升Java程序效率的各种策略、技巧和最佳实践。以下是根据标题和描述推测出的一些核心知识点: 1. **基础优化概念**:首先,优化涉及到理解程序的运行时...

Global site tag (gtag.js) - Google Analytics