来源于: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代码优化是提升应用程序性能的关键步骤,尤其是在大型企业级应用或者高性能服务中。优化能够减少内存消耗,提高程序运行速度,降低CPU使用率,并改善整体的用户体验。在Java开发领域,有多种工具可以帮助开发者...
Java代码优化是对程序进行改进的过程,旨在提升程序的运行效率,减少资源的消耗。优化主要关注两个方面:减小代码体积和提高代码执行效率。在Java中,性能问题往往源于编程习惯而非语言本身。以下是一些针对Java代码...
### Java代码优化技巧详解 #### 一、引言 在软件开发过程中,为了提升应用程序的性能,我们需要对Java代码进行优化。这是因为计算机系统的资源(如内存、CPU时间、网络带宽等)是有限的,而优化的目标就是使程序...
【Java代码优化编程】 在Java编程中,代码优化是一个关键环节,目的是使程序在有限的资源下更高效地运行。优化主要包括两个方面:减小代码体积和提高代码执行效率。以下是一些关于如何提高Java代码效率的具体策略:...
JAVA代码优化 JAVA代码优化 JAVA代码优化 JAVA代码优化 JAVA代码优化
Java代码优化是一个持续的过程,它包含了许多细节和技巧,能够帮助开发者编写出更高效、更易于维护的代码。在这44条Java代码优化建议中,我们可以提炼出一些核心的知识点,为Java编程实践提供参考。 首先,关于为...
java代码优化 个人感觉这写的不错. 值得学习!
非常实用的java代码优化策略详解,从变量声明、初始化、字符串链接、异常处理、IO、数组等各个方面进行优化,非常有参考价值。
代码优化,一个很重要的课题。可能有些人觉得没用,一些细小的地方有什么好修改的,改与不改对于代码的运行效率有什么影响呢?这个问题我是这么考虑的,像大海里面的鲸鱼一样,它吃一条小虾米有用吗?没用,但是,吃...
以上就是关于Java代码重构、优化以及设计优化的一些关键点,这些知识不仅能提升代码质量,还能帮助开发者更好地应对项目中的各种挑战。通过深入学习《重构-改善既有代码的设计》这样的经典书籍,你可以进一步提升...
Java代码优化是提升软件性能和效率的关键步骤,尤其是在大型企业级应用中,高效的代码能够显著降低服务器资源消耗,提高用户体验。这份"java代码优化编程共11页.pdf.zip"压缩包很可能包含了一份详尽的Java代码优化...
Java代码优化是提升应用程序性能的关键步骤,特别是在大型企业级应用或者高并发系统中,优化能够显著提高系统效率,减少资源消耗。"Java代码优化方法大全共5页.pdf"可能是一份详细介绍了Java代码优化核心策略的文档...
本压缩包"java代码优化1.0版本.zip"包含了一份详细的优化指南——"java代码优化1.0版本.md",以下是基于这个主题的Java代码优化相关知识点的详细阐述。 1. **基本语法优化** - **避免使用冗余代码**:删除无用的...
Java代码优化是提升程序性能、减少资源消耗的关键环节。这份"java代码优化细节总结1.0版本.7z"压缩包包含了一份详细的Java代码优化指南,适用于开发者在编写和优化Java程序时参考。以下是根据标题、描述以及压缩包内...
这份"java代码优化总结1.0版本.zip"资源可能包含了关于如何提升Java程序效率的各种策略、技巧和最佳实践。以下是根据标题和描述推测出的一些核心知识点: 1. **基础优化概念**:首先,优化涉及到理解程序的运行时...