java代码性能优化

摘要

性能优化一直是个难题,也是需要从一点一滴优化起。在我们日常编码中注意一些细节可以极大的提升性能。


正文

  1. map的遍历
    当遍历中需要同时用到key,value是使用entrySet迭代

    //反例
    for (Integer key : map.keySet()) {
        System.out.println(key+","+map.get(key));
    }
    
    //正例
    for (Map.Entry<Integer, String> entry : map.entrySet()) {
        System.out.println(entry.getKey()+","+entry.getValue());
    }
    
  2. 使用Collection.isEmpty()取代Collection.size()==0检测空
    任何 Collection.isEmpty() 实现的时间复杂度都是 O(1) ,但是某些 Collection.size() 实现的时间复杂度可能是 O(n) 。

    //反例
    if(ls.size()==0){
    	System.out.println("ls为空");
    }
    //正例
    List<String> ls=new ArrayList<>(10);
    if(ls.isEmpty()){
    	System.out.println("ls为空");
    }
    
  3. 集合初始化尽量指定大小
    集合扩容很复杂,所以尽量避免集合扩容

    //反例
    List<String> ls2=new ArrayList<>();
    //正例
    List<String> ls=new ArrayList<>(10);
    
  4. 字符串拼接使用 StringBuilder
    一般的字符串拼接在编译期 java 会进行优化,但是在循环中字符串拼接, java 编译期无法做到优化,所以需要使用 StringBuilder 进行替换。

    //反例
    String userName="";
    for (String user : users) {
        userName=userName+","+user;
    }
    //正例
    StringBuilder sb=new StringBuilder();
    for (String user : users) {
        sb.append(",");
        sb.append(user);
    }
    
  5. 频繁调用 Collection.contains 方法请使用Set
    List 的 contains 方法普遍时间复杂度是 O(n) ,如果在代码中需要频繁调用 contains 方法查找数据,可以先将 list 转换成 HashSet 实现,将 O(n) 的时间复杂度降为 O(1) 。

    //反例
    for (int i = 0; i <= Integer.MAX_VALUE; i++) {
        list.contains(i);
    }
    //正例
    Set<Integer> set = new HashSet(list);
    for (int i = 0; i <= Integer.MAX_VALUE; i++) {
        set.contains(i);
    }
    
  6. 使用String.valueOf(value)代替value+""和toString()

    //反例
    for (Integer i = 0; i < max; i++) {
         String str =i.toString();
     }
     for (Integer i = 0; i < max; i++) {
         String str =i+"";
     }
     //正例
     for (Integer i = 0; i < max; i++) {
         String str =String.valueOf(i);
     }
    
  7. 尽量避免在循环内部new局部变量
    创建变量不仅耗费时间而且消耗内存

    //反例
    for (String userName : users) {
        User user=new User();
        user.setName(userName);
        userList.add(user);
    }
    
    //正例
    User user=new User();
    for (String userName : users) {
        user.setName(userName);
        userList.add(user);
    }
    
  8. 尽量使用final修饰符
    带有final修饰符的类是不可派生的。在JAVA核心API中,有许多应用final的例子,例如java、lang、String,为String类指定final防止了使用者覆盖length()方法。另外,如果一个类是final的,则该类所有方法都是final的。java编译器会寻找机会内联(inline)所有的final方法(这和具体的编译器实现有关),此举能够使性能平均提高50%。

    private int id;
    //反例
    public int getId() {
        return id;
    }
    
    //正例
    final public int getId() {
        return id;
    }
    
  9. 尽量使用局部变量
    调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快;其他变量,如静态变量、实例变量等,都在堆(Heap)中创建,速度较慢。

  10. 慎用synchronized,尽量减小synchronize的方法
    实现同步是要很大的系统开销作为代价的,甚至可能造成死锁,所以尽量避免无谓的同步控制。synchronize方法被调用时,直接会把当前对象锁了,在方法执行完之前其他线程无法调用当前对象的其他方法。所以,synchronize的方法尽量减小,并且应尽量使用方法同步代替代码块同步。

  11. 尽量不要使用finalize方法
    将资源清理放在finalize方法中完成是非常不好的选择,由于GC的工作量很大,尤其是回收Young代内存时,大都会引起应用程序暂停,所以再选择使用finalize方法进行资源清理,会导致GC负担更大,程序运行效率更差。

  12. 在线程安全前提下应尽量使用HashMap、ArrayList
    HashTable、Vector等使用了同步机制,降低了性能。

  13. 量减少对变量的重复计算
    在循环中应该避免使用复杂的表达式,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快。

    //反例
    for(int i=0;i<list.size();i++){
    }
    //正例
    for(int i=0,len=list.size();i<len;i++){
    }
    
  14. 尽量在finally块中释放资源
    程序中使用到的资源应当被释放,以避免资源泄漏,这最好在finally块中去做。不管程序执行的结果如何,finally块总是会执行的,以确保资源的正确关闭。

  15. 尽量使用移位来代替’a/b’的操作
    "/"是一个代价很高的操作,使用移位的操作将会更快和更有效。但注意的是使用移位应添加注释,因为移位操作不直观,比较难理解。

    //反例
    int num = a / 4;
    int num = a / 8;
    //正例
    int num = a >> 2;
    int num = a >> 3;
    
  16. 尽量使用移位来代替’a*b’的操作
    对于’*'操作,使用移位的操作将会更快和更有效

    //反例
    int num = a * 4;
    int num = a * 8;
    //正例
    int num = a << 2;
    int num = a << 3;
    
  17. 尽量避免使用split
    除非是必须的,否则应该避免使用split,split由于支持正则表达式,所以效率比较低,如果是频繁的几十,几百万的调用将会耗费大量资源,如果确实需要频繁的调用split,可以考虑使用apache的StringUtils.split(string,char),频繁split的可以缓存结果。

  18. 尽量使用System.arraycopy ()代替通过来循环复制数组
    System.arraycopy() 要比通过循环来复制数组快的多。

    //反例
    System.arraycopy(user2,0,user3,0, user2.length);	
    
    //正例
    for (int i = 0; i < MAX_USER; i++) {
        user4[i]= user2[i];
    }
    
  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值