java程序优化有哪些注意事项和常用方法
2017-01-01 · 百度知道合伙人官方认证企业
育知同创教育
1【专注:Python+人工智能|Java大数据|HTML5培训】 2【免费提供名师直播课堂、公开课及视频教程】 3【地址:北京市昌平区三旗百汇物美大卖场2层,微信公众号:yuzhitc】
向TA提问
关注
展开全部
Java程序优化
1.String类 内部组成:1个char数组,1个int的偏移量,1个int的长度,内存空间主要消耗在char数组上。
其substring(int beginIndex, int endIndex)方法采用了空间换时间的做法,即使截取其中一个字符新生成的字符床依旧和原字符床持有相同的char数组,仅偏移量和长度不同而已,这无疑会造成内存的浪费,此方法的频繁使用会使永久区有可能出现内存泄漏(溢出)。
使用String(String original)此构造方法进行包裹可避开此风险:new String(str.substring(begin, end));这个构造方法可以削减无用的内存开销。
类似的还有:concat(String)/replace(char,char)/toLowerCase()/toUpperCase()/valueOf(char)等等,自行分析。
split(String regex)方法非常强大,支持正则分割,然而对于简单的(分割符都一样)分割,它的效率不是最好的。使用简单高效的StringTokenizer代替。最高效的方法:自己利用indexOf('')和substring(int,int)两个方法查找到第一个,然后截取,对剩下的字符串依旧进行此操作即可。结论:封装的越厉害,效率就会越低。实际开放中一般使用StringTokenizer即可。
字符串的charAt()也拥有超高的运行效率,如果要判断一个字符长如String str = "abcdefg"是否以"abc"开头,使用str.charAt(0)=='a' && str.charAt(0)=='b' && str.charAt(0)=='c' 要比str.startsWith("abc")更高效。
由于String类设计的内部结构是一个不变的char数组,一旦赋值就不能再改变,所以在需要频繁拼接的场景下多使用StringBuilder(高效非同步)、StringBuffer(同步),java的编译器会对字符串的累加自动变成StringBuilder优化(反编译可看到),但在循环里面也会不断的创建StringBuilder,故不能依赖编译器的优化,尽量使用StringBuilder做累加操作。另外初始化时候如果可以指定合适的容量,效果会更好。
2.ArrayList/Vector 基于数组 拥有很高的遍历效率 随机插入和删除效率低 LinkedList则相反 ,另外它们的三种遍历方法中for循环效率最高,forEach最低,迭代器居中。
3.HashMap(双列,k/v) 通过对key计算hash直接映射内存地址,其检索速度超快,注意不要用糟糕的hashCode覆盖原有方法,最好给一个有意义(保证对象间不冲突)的实现
4.HashSet(单列) 的内部是一个HashMap,它使用HashMap的key列存储数据,value列全部置空,因此它拥有HashMap同样高的检索性能。由于HashMap不允许key重复,故HashSet不允许插入重复值。
5.LinkedHashMap 继承自HashMap,自然拥有了其优良特性,并且通过内部维护一个元素顺序(先进先出)链表弥补了HashMap的元素无顺序的缺陷,还可以设置按访问时间排序。
6.LinkedHashSet 继承自HashSet。
7.TreeMap也是一个有序的Map,它的顺序依赖value对象的排序规则,它有subMap(k2,k3):介于k2、k3之间,headMap(k2):大于k2,tailMap(k3):小于k3 等特色功能。
8.TreeSet 对 TreeMap 包装
9.NIO:提升I/O性能的两大组件:Channel、Buffer 对于大文件的复制性能较高
10.强引用:所指对象在任何情况下都不会被回收,可能会引起内存泄漏。
软引用(SoftReference):一个持有软引用的对象不会立即被回收,在临近阀值时被回收,可以使用一个引用队列,当对象被回收时会加入到这个队列中。适合做可有可无的数据缓存。
弱引用(WeakReference):只要GC即被回收。适合做可有可无的生命周期更短的数据缓存。
虚引用(PhantomReference):最弱的引用,和没有引用几乎是一样的,随时会被gc回收,它的作用主要是跟踪gc过程。
11.慎用异常:try-catch 语句频繁使用会对性能影响很大,切勿通过try-catch异常捕捉来完成业务逻辑,如非必要请少用。
13.静态变量、实例变量存放于堆中,远没有栈中变量访问效率高,所以如果一个变量若无被共享等需求应尽量在栈中初始化即在方法中定义和访问。
14.在所有的运算中,位运算最高效。如果可以优先选择位运算如:乘以2 x <<= 1 除以2 x >>= 1
15.switch 语句类似 if-else 性能虽然不差但也有提升空间,不可滥用,可以尝试将switch分支的结果存放于一个数组内,然后通过一个判断逻辑从数组内获取,这个判断逻辑自己写的可以超过switch内部的分支判断语句。如果遇到很多分支结构的判断可以去考虑下“状态模式”来设计程序。
16.如果有多条计算语句它们的某些部分是相同,那么可以把相同的语句提取成公共的,计算一次后保存计算结构供每个表达式用,可以节省cpu资源,避免重复计算表达式,尤其在循环内部,这种优化是有必要的。
17.减少循环次数:举例:for(int i=0;i<9999;i+=3){arr[i]=i;arr[i+1]=i+1;arr[i+2]=i+2;}
18.arraycopy()是native方法效率很高,如果有可能我们应该尽量使用native的方法以最大限度提高性能。
19.clone()方法可以绕过类的构造方法,对于构造耗时的对象可以考虑使用,但要注意默认的clone实现的是一个浅拷贝,如需要深拷贝需要重载clone方法。
1.String类 内部组成:1个char数组,1个int的偏移量,1个int的长度,内存空间主要消耗在char数组上。
其substring(int beginIndex, int endIndex)方法采用了空间换时间的做法,即使截取其中一个字符新生成的字符床依旧和原字符床持有相同的char数组,仅偏移量和长度不同而已,这无疑会造成内存的浪费,此方法的频繁使用会使永久区有可能出现内存泄漏(溢出)。
使用String(String original)此构造方法进行包裹可避开此风险:new String(str.substring(begin, end));这个构造方法可以削减无用的内存开销。
类似的还有:concat(String)/replace(char,char)/toLowerCase()/toUpperCase()/valueOf(char)等等,自行分析。
split(String regex)方法非常强大,支持正则分割,然而对于简单的(分割符都一样)分割,它的效率不是最好的。使用简单高效的StringTokenizer代替。最高效的方法:自己利用indexOf('')和substring(int,int)两个方法查找到第一个,然后截取,对剩下的字符串依旧进行此操作即可。结论:封装的越厉害,效率就会越低。实际开放中一般使用StringTokenizer即可。
字符串的charAt()也拥有超高的运行效率,如果要判断一个字符长如String str = "abcdefg"是否以"abc"开头,使用str.charAt(0)=='a' && str.charAt(0)=='b' && str.charAt(0)=='c' 要比str.startsWith("abc")更高效。
由于String类设计的内部结构是一个不变的char数组,一旦赋值就不能再改变,所以在需要频繁拼接的场景下多使用StringBuilder(高效非同步)、StringBuffer(同步),java的编译器会对字符串的累加自动变成StringBuilder优化(反编译可看到),但在循环里面也会不断的创建StringBuilder,故不能依赖编译器的优化,尽量使用StringBuilder做累加操作。另外初始化时候如果可以指定合适的容量,效果会更好。
2.ArrayList/Vector 基于数组 拥有很高的遍历效率 随机插入和删除效率低 LinkedList则相反 ,另外它们的三种遍历方法中for循环效率最高,forEach最低,迭代器居中。
3.HashMap(双列,k/v) 通过对key计算hash直接映射内存地址,其检索速度超快,注意不要用糟糕的hashCode覆盖原有方法,最好给一个有意义(保证对象间不冲突)的实现
4.HashSet(单列) 的内部是一个HashMap,它使用HashMap的key列存储数据,value列全部置空,因此它拥有HashMap同样高的检索性能。由于HashMap不允许key重复,故HashSet不允许插入重复值。
5.LinkedHashMap 继承自HashMap,自然拥有了其优良特性,并且通过内部维护一个元素顺序(先进先出)链表弥补了HashMap的元素无顺序的缺陷,还可以设置按访问时间排序。
6.LinkedHashSet 继承自HashSet。
7.TreeMap也是一个有序的Map,它的顺序依赖value对象的排序规则,它有subMap(k2,k3):介于k2、k3之间,headMap(k2):大于k2,tailMap(k3):小于k3 等特色功能。
8.TreeSet 对 TreeMap 包装
9.NIO:提升I/O性能的两大组件:Channel、Buffer 对于大文件的复制性能较高
10.强引用:所指对象在任何情况下都不会被回收,可能会引起内存泄漏。
软引用(SoftReference):一个持有软引用的对象不会立即被回收,在临近阀值时被回收,可以使用一个引用队列,当对象被回收时会加入到这个队列中。适合做可有可无的数据缓存。
弱引用(WeakReference):只要GC即被回收。适合做可有可无的生命周期更短的数据缓存。
虚引用(PhantomReference):最弱的引用,和没有引用几乎是一样的,随时会被gc回收,它的作用主要是跟踪gc过程。
11.慎用异常:try-catch 语句频繁使用会对性能影响很大,切勿通过try-catch异常捕捉来完成业务逻辑,如非必要请少用。
13.静态变量、实例变量存放于堆中,远没有栈中变量访问效率高,所以如果一个变量若无被共享等需求应尽量在栈中初始化即在方法中定义和访问。
14.在所有的运算中,位运算最高效。如果可以优先选择位运算如:乘以2 x <<= 1 除以2 x >>= 1
15.switch 语句类似 if-else 性能虽然不差但也有提升空间,不可滥用,可以尝试将switch分支的结果存放于一个数组内,然后通过一个判断逻辑从数组内获取,这个判断逻辑自己写的可以超过switch内部的分支判断语句。如果遇到很多分支结构的判断可以去考虑下“状态模式”来设计程序。
16.如果有多条计算语句它们的某些部分是相同,那么可以把相同的语句提取成公共的,计算一次后保存计算结构供每个表达式用,可以节省cpu资源,避免重复计算表达式,尤其在循环内部,这种优化是有必要的。
17.减少循环次数:举例:for(int i=0;i<9999;i+=3){arr[i]=i;arr[i+1]=i+1;arr[i+2]=i+2;}
18.arraycopy()是native方法效率很高,如果有可能我们应该尽量使用native的方法以最大限度提高性能。
19.clone()方法可以绕过类的构造方法,对于构造耗时的对象可以考虑使用,但要注意默认的clone实现的是一个浅拷贝,如需要深拷贝需要重载clone方法。
推荐律师服务:
若未解决您的问题,请您详细描述您的问题,通过百度律临进行免费专业咨询