java 语法层面调优

来源:互联网 发布:电脑怎么卸载软件 编辑:程序博客网 时间:2024/05/22 08:02

主要是针对java语法层面的优化


  1. 使用Clone()方式创建对象
    采用clone()方式是直接复制当前对象的所有信息,不会调用对象的构造函数。性能得到提升,但是clone()方法是浅克隆,如果对象中有引用对象,则直接将引用复制。
  2. 避免对boolean进行判断
    如string.endswith(“a”) == true。
    在表达式本身就是boolean值结果的时候,避免比较可以使代码执行更快且更整洁。
  3. 使用三目运算符替换if-else。
if(){}else{}

等价于

表达式 ? a : b

好处是代码变短,并且JVM在做代码优化时也是相同的处理。
4. 静态方法替换实例方法
因为实例方法需要维护一张类似虚拟函数导向表的结构,以便实现多态。
静态方法可以通过类名.方法或者对象.方法。
静态方法只能调用静态变量,所以不会改变对象状态。
静态方法可以更快的调用。
5. 使用final关键字
将方法锁定,防止继承类修改。
6. 避免不需要的instanceof操作。
7. 避免子类中存在父类转换
可以直接将子类对象赋值给父类引用,不需要转换。
8. 建议多使用局部变量
局部变量保存在栈里面,读写较快,且回收方便。
静态变量(类变量),静态变量和实例变量都属于全局变量。
9. 运算效率最高的方式——位运算
- >>> 和 >> 的区别:>>>操作数高位补0,>>操作数高位移入原来高位的值。
- 右移一位相当于除以2,左移一位相当于乘以2
- 若进行位逻辑运算的两个操作数的数据长度不一样,则返回值应该是数据长度较长的数据类型。
- 按位异或可以不适用临时变量完成两个值得交换,也可以使某个整型数的特定位的值翻转。
- 按位与运算可以用来屏蔽特定的位,也可以用来取某个整型数的某些特定位。
- 按位或运算可以用来对某个整型数的特定位置为1
10. 用一维数组代替二位数组
二维数组的访问速度优于一维数组,当内存空间却是一维数组的10倍。
11. 布尔运算代替位运算
逻辑或、逻辑与只要条件满足,则可以忽略后续表达式,而位运算则需要计算全部表达式。
在条件判断时,避免使用位运算。
12. 提取表达式优化
例:

for(){    b1 = a1 * a2 * a3 / 3 * 4 * a3 * a4;    b1 = a1 * a2 * a4 / 3 * 4 * a4 * a4;}

提取表达式:

for(){    combine = a1 * a2 / 3 * 4 * a3 * a4;    b1 = combine * a3;    b1 = combine * a4;}

13.少用取反操作符(!)
取反操作表示异或。使用方便但降低了程序可读性。
14. 不要重复初始化变量
类的成员属性会在调用构造函数时,默认初始化。
当给成员变量设置初始值时,又要调其他方法,最好放在一个方法里面,因为调用某方法赋值可能会因为类尚未初始化而抛出空指针异常。
15. 在switch()中使用字符串进行条件匹配,这个功能是在jdk 1.7才支持。
16. 数值字面量
数字默认为十进制。
八进制在整数字面量前面加0
十六进制在数字前面加0x(0X)
二进制在数字前面加0b(0B), > jdk1.7
为了便于阅读,可以在数字中间加入下划线“_”,不影响使用。但不允许在数字开头及末尾加下划线。
17. 针对基本数据类型的优化
字符串内部化,即字符串常量池,相同的字面量字符串指向同一个对象。
-128~127的short、int、char以及包装类对象指向相同的对象。
18. 空变量
在方法中,局部变量在方法结束时,会自动被编译器赋值null,然后被回收。但是如果在方法中,使用了静态变量,则只要所在类加载在虚拟机中,则变量将一直存在,直到对它进行重新赋值,上一个对象才会被回收。并且如果静态变量占用空间特别大,在eden区不足的时候,可能进行老年代担保直接进入老年代,则该对象被回收的时间则更加延后了。但每次使用后赋值null,则可以保证静态变量被立即回收。
19. List.subList(int fromIndex,int toIndex);返回子集合,但是父集合和子集合的修改都会相互影响。
20. 集合内部避免返回null。
返回null,则在使用时,需要添加判空代码。可以返回空集合或者空数组。Collections.emptyList();注意返回的空集合是不允许被修改的。
21. 判断数组中是否有某个元素。而不需要使用循环遍历。

ArrayList.asList(T[] array).contains(T obj);

22.ArrayList与LinkedList

ArrayList底层采用数组实现,对数据的随机访问比较快,但是在数据的增加或者删除则需要移动大量的元素,越靠前,则消耗越大。并且在容量大小需要扩展时,同样需要复制大量数组。而LinkedList则采用链表的方式实现,对于数据的访问需要通过循环的方式,但是对于添加和删除元素则比较简单。由于内部需要维护Entry对象,则占用空间比较大。
23. Vector和HashTable是线程安全的。ArrayList、HashMap是非线程安全的。Collections.synchronized(List list),返回一个线程安全的同步列表。Collections.synchronized(Map K,V> m);返回一个线程安全的同步HashMap。
24. HashMap底层使用的是链表数组。即每个数组中存放的是链表的头结点。首先,通过对象的hash值,来找到数组下标,然后如果该下标处没有元素,则存放该节点。否则,存放该节点并在节点中引用前一个节点构成链表。获取元素时,如果该下标处有多个节点,则需要循环遍历。
25. HashSet内部通过封装HashMap来完成功能。
26. LinkedHashMap保存元素加入时的顺序。
27. TreeMap则根据key进行排序,排序方式可以由Compartor或Comparable确定。
28. 迭代器
- java 1.2

Iterator i = xxx.iterator();while(i.hasNext()){    System.out.println(i.next());}
  • java 5
for(String item : items){    System.out.println(temp);}
  • java 8(lambda表达式)
List<String> lists = new LinkedList<>();……lists.forEach(item->System.out.println(item));

29.流
流是应用在一组元素上的一次执行的操作序列。集合和数组都可以用来产生流。
流不存储集合中的元素。
流管道由数据源、若干个中间操作、一个最终操作组成。
中间操作对数据集完成检索、过滤等中间业务。
最终操作完成对数据集的最终处理。
例:完成对长度大于12的单词计数。

List<String> words = new ArrayList();......long count = words.stream().filter(w -> w.length() > 12 ).count();

Stream操作符不会改变源对象。
Steam操作符可能是延迟执行的。

并行计算:

List<String> words = new ArrayList();......long count = words.parallelStream().filter(w -> w.length() > 12 ).count();

parallelStream自动才用多线程进行并行计算。但执行顺序可能会发生变化


中间操作包括:distinct()、sorted()、map()等。

最终方法包括:forEach()、allMatch()、anyMatch()、findAny()、findFirst()、sum()、max()、min()、averag()等。
30. String对象
String成员变量声明:

private final char value[];private final int offset;private final int count;private int hash;

一个空String所占空间:对象头(8个字节)+ char数组(16个字节)+ 3个int(12个字节) + 一个char数组引用(4个字节) = 40字节
new String(“abc”)会在堆中分配内存,而使用字面量常量,则在常量池中创建。
在用“+”拼接字符串时,会产生中间对象。所以尽量使用StringBuilder。
String对象一旦生成,则不能对它进行改变。
str1.intern() == str2.intern();比较两个字符串是否来自执行一个常量池对象。
substring();方法公用原字符串数组对象,只是改变了偏移量。
31. 用charat()代替startswith();性能比较快
32. 在字符串相加的时候,如果只有一个字符,在使用单引号。
string a = “abc”+’d’;
33. 字符串切割中,性能StringTokenizer > substring() > split();
34. 字符串重编码:

String s = "张三";String s1 = new String(s.getBytes("UTF-8"),"UTF-8");

35.字符串拼接:StringBuilder > concat() > “+”; “+”表示直接拼接字符串。
36. 强引用:直接引用,可以导致OOM.
37. 软引用:如果内存足够的时候,就保存对象。否则,则回收。通过java.lang.ref.SoftReference使用。
38. 弱引用:通过java.util.WeakHashMap类使用。
39. 幽灵引用:在对象被回收时得到通知,不能通过幽灵引用来获取被引用的对象。
40. try-catch处理多个异常(> 1.7)

try{}catch(Exception A | Exception B){}
  1. 避免在循环中调用同步方法,但可以在同步代码块中,循环调用非同步方法。
public synchronized void method(){}for(){    method();}改为:public void method(){};synchronized{    for(){        method();    }}

42.当循环嵌套时,应该把次数多的放在内侧。因为需要创建的循环遍历更少。

for(int i = 0; i < 100;i++){    for(int j = 0 ; j < 100000; j++){        // 只需要创建100个j变量,反之则需要100000个。    }}

43.当判断条件多于2时才考虑switch语句。
44. 减少循环次数

for(int i =0;i<99999;i++){    a[i] = i;}for(int i =0;i<99999;i+=3){    a[i] = i;    a[i+1] = i+1;    a[i+2] = i+2;}

45.将变量声明在循环体外部
46. 使用System.arraycopy()来进行数组复制。因为底层调用native方法,效率更快。
47. 进行I/O操作的时候,使用缓存流。
OutputStream -> FileOutputStream -> BufferedOutputStream
InputStream -> FileInputStream -> BufferedInputStream
Writer -> FileWriter -> BufferedWriter
Reader -> FileReader -> BufferedReader
48. 在finally中释放或者关闭资源的占用。
49. 不使用中间变量交换数据

a = a + b;b = a - b;a = a - b;
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 带介指手指月肿了拿不下来怎么办 老公搞建筑的要长期在外地怎么办 媳妇跟婆婆吵架老公帮婆婆该怎么办 在家里礼佛香炉剩下的香头怎么办 精索曲张最近一打篮球就蛋疼怎么办 都两天了快递还是显示已发货怎么办 中通快递到达一天就是不派送怎么办 顺丰派送员把快递寄错了怎么办 顺丰快递把户籍卡弄丢了怎么办 金立手机不小心设置成英文了怎么办 三星手机不小心设置成英文了怎么办 手游方舟国际版渡渡鸟跟丢了怎么办 一打电话4g变2g怎么办 手机4g突然变2g怎么办 江湖风云录八卦门任务拒绝了怎么办 百度网盘下载时显示违规信息怎么办 在海马助手下载的游戏闪退怎么办 手机版百度云盘不能普通下载怎么办 手机版百度云盘一直加载中怎么办 登别人的网盘单同步通讯录了怎么办 被培训公司骗了贷款之后该怎么办 乐教乐学孩子登陆你那忘记了怎么办 脸擦破了痂掉了留斑怎么办 挤黑头后鼻子又红又疼怎么办 香奈儿邂逅清新淡香水不喷怎么办 脚面被压了肿起来了怎么办 每天加班很累反而失眠严重怎么办 减肥药吃了口臭嘴巴苦怎么办 上火引起的牙疼怎么办吃什么药 舌苔厚口气重怎么办应该吃什么药 宝宝老是额头热四肢不热怎么办 考老师考砸了心理崩溃了怎么办 苹果手机一会白屏一会黑屏怎么办 360云盘的东西删不了怎么办 手机邮箱打开的文件疑似病毒怎么办 电脑qq发送的文件失效了怎么办 小米4c温控文件打开是乱码怎么办 超星尔雅用学号登录密码忘了怎么办 全脸做激光去黄褐斑后脸发红怎么办 上传到微云中的视频下载不了怎么办 微云保存的小电影下载不了怎么办