java常用重构优化总结--自己亲身体验

代码重构
  6大原则:
    单一职责原则(一个类最好最好只有一种行为动机,太多承担职责会导致耦合度太高)、
    开放封闭原则(功能可以扩展,但是不可以内部修改)、
    依赖倒转原则(应该依赖抽象而不应该依赖具体对象)、
    里氏代换原则(父类都替换成它的子类程序的行为没有变化。 正是有了里氏代换原则,才使得”开-闭“原则成为了可能)、
    接口隔离原则(为同一个角色提供宽、窄不同的接口,以对付不同的客户端)、
    迪米特法则(最少知道原则;如果两个类不必彼此直接通信,那么这两个类就不应当发生直接的相互作用)
  设计模式应用:
    <1. 适配器模式(由原来sphinx适配为solr应用)
    <2. 抽象工厂方法模式+反射+配置文件实现可配置的动态化(csv、bean、json等)
    <3. 建造者模式:将一个复杂对象的构建与它的表示分离,使得同样的构建过程可以创建不同的表示
        主要用于解析客户端传过来的查询条件进行构造和封装,生成对应的solrQuery。以及最后查询完毕之后构建分装成对应返回的json格式
    <4. 过滤器模式:允许开发人员使用不同的标准来过滤一组对象,通过逻辑运算以解耦的方式把它们连接起来
        过滤筛选传入查询时间、过滤目前已经有的集群定位查询范围(hot/recent/warm/all)
    <5. 观察者模式:定义了一种一对多的依赖关系,让多个观察者对象同时监听某一个主题对象。这个主题对象在状态发生变化时,会通知所有观察者对象,使他们能够自动更新自己(模拟ZK)
        实时预处理触发更新底层依赖数据库更新。
        多个更新类注册到统一监听器上 + 缓存mamcache + 出发更新模块(监控数据库数据变化+指标) + 数据库

代码调优
    <1. 可以指定final修饰的类和方法那就一定要指定,java编译器会内联所有的final方法,提升java运行效率。Java编译器会寻找机会内联所有的final方法,内联对于提升Java运行效率作用重大,具体参见Java运行期优化。此举能够使性能平均提高50%。
    <2. 字符串拼接不能使用+来拼接,底层会创建一个新对象,这两个对象相拼接,应该使用StringBuilder/StringBuffer
    <3. 尽量使用局部变量。因为这是在栈中创建,随着方法的运行结束这些内容就消失了,不需要额外的垃圾回收
    <4. 在一些大的循环时,尽量减少重复计算;例如for循环中的length

  对方法的调用,即使方法中只有一句语句,也是有消耗的,包括创建栈帧、调用方法时保护现场、调用方法完毕时恢复现场等。所以例如下面的操作:

    for (int i = 0; i < list.size(); i++)

    {...}

  建议替换为:

    for (int i = 0, int length = list.size(); i < length; i++)

    {...}

  这样,在list.size()很大的时候,就减少了很多的消耗

<5. 尽量使用懒加载方式即在需要的时候才去创建
    <6. 不要在循环中使用try...catch...
    <7. 在可以评估出待添加内容的长度,那么在初始化容器的时候就直接指定开辟那么大的空间,HashMap除外,大概开辟2的次幂大小就可以了,因为它底层是列表形式存储

  比如ArrayList、LinkedLlist、StringBuilder、StringBuffer、HashMap、HashSet等等,以StringBuilder为例:

  (1)StringBuilder()      // 默认分配16个字符的空间

  (2)StringBuilder(int size)  // 默认分配size个字符的空间

  (3)StringBuilder(String str) // 默认分配16个字符+str.length()个字符空间

  可以通过类的初始化函数来设定它的初始化容量,这样可以明显地提升性能。比如StringBuilder吧,length表示当前的StringBuilder能保持的字符数量。因为当StringBuilder达到最大容量的时候,它会将自身容量增加到当前的2倍再加2,无论何时只要StringBuilder达到它的最大容量,它就不得不创建一个新的字符数组然后将旧的字符数组内容拷贝到新字符数组中—-这是十分耗费性能的一个操作。试想,如果能预估到字符数组中大概要存放5000个字符而不指定长度,最接近5000的2次幂是4096,每次扩容加的2不管,那么:

  (1)在4096的基础上,再申请8194个大小的字符数组,加起来相当于一次申请了12290个大小的字符数组,如果一开始能指定5000个大小的字符数组,就节省了一倍以上的空间

  (2)把原来的4096个字符拷贝到新的的字符数组中去

  这样,既浪费内存空间又降低代码运行效率。所以,给底层以数组实现的集合、工具类设置一个合理的初始化容量是错不了的,这会带来立竿见影的效果。但是,注意,像HashMap这种是以数组+链表实现的集合,别把初始大小和你估计的大小设置得一样,因为一个table上只连接一个对象的可能性几乎为0。初始大小建议设置为2的N次幂,如果能估计到有2000个元素,设置成new HashMap(128)、new HashMap(256)都可以。

<8. 当复制大量数据时最好使用System.arrayCopy()方法 [当内容长度大于10000左右,使用此方法,否则太小的话使用for循环比较快]
    <9. 乘法、除法尽量使用位运算
    <10. 循环内不要创建对象
    <11. 不要创建不使用的对象、不要引入不用到的引用。
    <12. 使用数据库就使用数据库连接池
    <13. 使用带缓冲的输入输出流进行IO操作:BufferedReader、BufferedInputStream / BufferedWriter、BufferedOutputStream

  BufferedReader会一次性从物理流中读取8k(默认数值,可以设置)字节内容到内存,如果外界有请求,就会到这里存取,如果内存里没有才到物理流里再去读。即使读,也是再8k。  如果不使用BufferedReader而直接读物理流,是按字节来读,对物理流的每次读取,都有IO操作。IO操作是最耗费时间的。BufferedReader就是减少了大量IO操作,而为你节省了时间。

  简单的说,一次IO操作,读取一个字节也是读取,读取8k个字节也是读取,两者花费时间相差不多。而一次IO的来回操作却要耗费大量时间。

  好比是一辆大型汽车(设装100人),要去车站接人到公司,接一个人也是接,接100个人也是接,而时间一样。显然,接100个人最划算。

物理流就是一次一个字节(一个人)

Buffered就是一次8k个字节(100个人)

对于读取定长字节文件,当然BufferedReader更快了!

<14. 基本类型转换为字符串,最快的使用.toString()方法

  所以以后遇到把一个基本数据类型转为String的时候,优先考虑使用toString()方法。至于为什么,很简单:

  1、String.valueOf()方法底层调用了Integer.toString()方法,但是会在调用前做空判断

  2、Integer.toString()方法就不说了,直接调用了

  3、i + “”底层使用了StringBuilder实现,先用append方法拼接,再用toString()方法获取字符串

  三者对比下来,明显是2最快、1次之、3最慢

<15. 遍历map对应的key-value,最好使用iterator的EntrySet方式;如果只是使用key值,则使用 hm.keySet();更加合理
    <16. 多使用一些apache下提供的包:StringUtils、Collections判空、Arrays转换list,或者使用Guava:Joiner、Splitter、Strings、Maps判空

时间: 2024-10-15 07:16:38

java常用重构优化总结--自己亲身体验的相关文章

Java程序性能优化——设计优化

原文出自:http://blog.csdn.net/anxpp/article/details/51914119,转载请注明出处,谢谢! 1.前言 OK,之前写了一篇文章:"23种设计模式介绍以及在Java中的应用"详细介绍了如何将设计模式应用到Java编程中,而本文旨在介绍如何利用他们优化我们的程序,使其性能更佳. 设计模式的详细介绍请参照上面链接中的文章,不是本文的重点. 而Java程序的性能优化,不一定就仅仅是以提高系统性能为目的的,还可能是以用户体验.系统可维护性等为目的. 2

Java程序性能优化——性能指标

性能概述 为什么程序总是那么慢?它现在到底在干什么?时间都花到哪里去了?也许,你经常会抱怨这些问题.如果是这样,那说明你的程序出了性能问题.和功能性问题相比,性能问题在有些情况下,可能并不算什么太大的问题,将就一下,就过去了!但是,严重的性能问题会导致程序瘫痪.假死.直至崩溃.本节就先来认识性能的各种表现和指标. 看懂程序的性能 读客户端程序而言,拙劣的性能会严重影响用户体验:界面停顿.抖动(非动作特效).响应迟钝等问题会遭到用户不停的抱怨.一个典型的例子就是Eclipse IDE工具在Full

Java的性能优化

http://www.toutiao.com/i6368345864624144897/?tt_from=mobile_qq&utm_campaign=client_share&app=news_article&utm_source=mobile_qq&iid=4452590055&utm_medium=toutiao_android Java的性能优化 万能的乐乐老师 2016-12-26 17:54 Play Video 做Java基础的朋友可以加群:15449

Java常用英语汇总(面试必备)

Java常用英语汇总(面试必备) abstract (关键字)             抽象 ['.bstr.kt] access                            vt.访问,存取 ['.kses]‘(n.入口,使用权) algorithm                     n.算法 ['.lg.riem] annotation                     [java]代码注释 [.n.u'tei..n] anonymous                

java常用英语单词

abstract (关键字) 抽象 ['.bstr.kt] access vt.访问,存取 ['.kses]'(n.入口,使用权) algorithm n.算法 ['.lg.riem] annotation [java]代码注释 [.n.u'tei..n] anonymous adj.匿名的[.'n.nim.s]' (反义:directly adv.直接地,立即[di'rektli, dai'rektli]) apply v.应用,适用 [.'plai] application n. 应 用 ,

java常用正则表达式

java常用正则表达式 1.^\d+$ //匹配非负整数(正整数 + 0) 2.^[0-9]*[1-9][0-9]*$ //匹配正整数 3.^((-\d+) ?(0+))$ //匹配非正整数(负整数 + 0) 4.^-[0-9]*[1-9][0-9]*$ //匹配负整数 5.^-?\d+$ //匹配整数 6.^\d+(\.\d+)?$ //匹配非负浮点数(正浮点数 + 0) 7.^(([0-9]+\.[0-9]*[1-9][0-9]*) ?([0-9]*[1-9][0-9]*\.[0-9]+)

Java程序性能优化——性能调优层次

为了提升系统性能,开发人员可以从系统的各个角度和层次对系统进行优化.除了最常见的代码优化外,在软件架构上.JVM虚拟机层.数据库以及操作系统层都可以通过各种手段进行调优,从而在整体上提升系统的性能. 设计调优 设计调优处于所有调优手段的上层,它往往需要在软件开发之前进行.在软件开发之初,软件架构师就应该评估系统可能存在的各种潜在的问题,并给出合理的设计方案.由于软件设计和架构对软件整体有决定性的影响,所以,设计调优对系统性能的影响也是最大的.如果说,代码优化.JVM优化都是对系统微观层面上"量&

Java程序性能优化技巧

多线程.集合.网络编程.内存优化.缓冲..spring.设计模式.软件工程.编程思想 1.生成对象时,合理分配空间和大小new ArrayList(100); 2.优化for循环Vector vect = new Vector(1000);for( inti=0; i<vect.size(); i++){ ...}for循环部分改写成:int size = vect.size();for( int i=0; i>size; i++){ ...} 如果size=1000,就可以减少1000次si

[JAVA] java程序性能优化

一.避免在循环条件中使用复杂表达式 在不做编译优化的情况下,在循环中,循环条件会被反复计算,如果不使用复杂表达式,而使循环条件值不变的话,程序将会运行的更快. 例子: import java.util.vector; class cel { void method (vector vector) { for (int i = 0; i < vector.size (); i++) // violation ; // ... } } 更正: class cel_fixed { void metho