码迷,mamicode.com
首页 > 编程语言 > 详细

Java程序优化

时间:2020-03-28 17:54:34      阅读:79      评论:0      收藏:0      [点我收藏+]

标签:读取   次数   轻量级   需要   遍历   静态方法   一起   dHash   nal   

一. 字符串优化处理

1. String对象组成:char数组,offset偏移量,count长度;

2. String对象特点:

不变性:String对象一旦生成,则不能再对它进行改变;

针对常量池的优化:当两个String对象拥有相同的值时,他们只引用常量池中的同一个拷贝;

类的final定义;

3. subString()

subString()方法之所以会引起内存泄漏,是因为调用了String(int offset, int count, char value[])构造函数,此构造函数采用了用空间换时间的手段,截取字符串时原生内容被复制到了新的字符串中;

4. 字符串的分割与查找

String.split()方法使用简单,功能强大,但是在性能敏感的系统中频繁使用这个方法是不可取的;

StringTokenizer性能优于split()方法;

StringTokenizer st = new StringTokenizer(orgStr, ";");
for(int i = 0; i < 10000; i ++) {
    while (st.hasMoreTokens()) {
        st.nextToken();
    }     
    st = new StringTokenizer(orgStr, ";")    
}

使用indexOf()和subSting()实现的分割算法性能最好,可读性和可维护性最差;

String tmp = orgStr;
for(int i = 0; i < 10000; i ++) {
    while(true) {
        String splitStr = null;
        int j = tem.indexOf(;);
        if(j < 0) break;
        splitStr = tmp.subString(0, j);
        tmp = tmp.subString(j + 1);
    }
    tmp = orgStr;
}

5. charAt()

orgStr.charAt(0) == ‘a‘ && orgStr.charAt(0) == ‘b‘ && orgStr.charAt(0) == ‘c‘ 效率高于orgStr.startsWith("abc");

6. StringBuffer和StringBuilder

对于String常量的累加操作,在编译时会进行优化,将多个连接操作的字符串在编译时合成一个单独的长字符串,并不会生成多个String实例;

对于String变量的累加操作,也做了相应的优化操作,使用了StringBuilder对象来实现字符串的累加;

对于String操作,类似于“+”和“+=”的运算符应该尽量少用,concat()方法的效率远远高于“+”和“+=”运算符,但又低于StringBuilder类;

StringBuilder的效率高于StringBuffer,但无法保证线程安全;

StringBuilder/StringBuffer的默认容量是16字节,超出容量需要扩容,扩容策略是将原有的容量大小翻倍,申请新的内存空间,将原数组中的内容复制到新数组,所以如果能预估StringBuilder/StringBuffer的大小,将能够有效的节省这些操作;

二. 核心数据结构

1. List接口

ArrayList和Vector使用了数组实现,初始值大小为10,每次扩容为1.5倍,唯一区别是Vector是线程安全的;

LinkedList使用了循环双向链表的数据结构;

增加元素到列表尾端:因为数组的连续性,总是在尾端增加元素时,只有在空间不足时才产生数组扩容和数组复制,大部分的追加操作效率非常高,LinkedList每次增加元素都需要新建一个Entry对象,并进行更多的赋值操作,对性能有一定的影响;

增加元素到列表任意位置:插入的元素在List中的位置越靠前,数组重组的开销就越大,可以考虑用LinkedList代替ArrayList;

删除任意位置元素:在ArrayList的每一次删除操作后都需要进行数组的重组,位置越靠前,开销越大;对于LinkedList,双向链表在查找要删除的元素时效率很高,但是移除中间元素则几乎要遍历半个List,在数据量很大时效率很低;所以在删除头或尾部的数据时,可以采用LinkedList,移除中间的元素时使用ArrayList;

对于LinkedList进行随机访问时,总会进行一次列表的遍历操作,所以使用for循环遍历的性能是很差的;forEach在编译后比迭代器多了一步赋值操作,导致性能略差一些;

2. Map接口

HashMap是将key做hash算法,将hash值映射到内存地址,直接取得key对应的数据;底层采用数组实现,内存地址即数组的下标索引;

LinkedHashMap是一个维护了元素次序表的HashMap,可以提供元素插入时的顺序或最近访问的顺序两种实现;

所有的集合都不允许在迭代器模式中修改集合的机构,否则会抛出ConcurrentModificationException,LinkedHashMap在根据元素对吼访问时间进行排序的模式中,没当使用get()方法访问某一元素时,该元素便被移动到链表的尾端,所以此时不能在迭代器中使用get()操作;

TreeMap内部基于红黑树实现,可以根据key进行排序;

3. Set接口

所有Set的实现,都只是对应的Map的一种封装而已;

三. 使用NIO提升性能

1. Channel是一个双向通道,既可读,也可写,但不能直接对Channel进行读写操作,必须通过Buffer来进行;

2. Buffer中有3个重要参数:位置position,容量capacity,上限limit;

3. MappedByteBuffer可以大大提高读取和写入文件的速度,可以适当使用这种方式;

4. 在对普通的ByteBuffer访问时,系统总是会使用一个“内核缓冲区”进行间接的操作,而DirectBuffer所处的位置就相当于这个“内核缓冲区”,由于是更加接近系统底层的方法,所以速度更快;

5. 创建和销毁DirectBuffer的成本较高,所以在频繁创建Buffer的场合不适用,如果可以复用DirectBuffer,可以大幅改善性能;

四. 引用类型

强引用:直接访问目标对象;不会被系统回收;可能导致内存泄漏;

软引用:当堆使用率接近阈值时才会被JVM回收,可以用于实现对内存敏感的Cache;

弱引用:在系统GC时,只有发现弱引用,便会进行回收;软引用,弱引用都可用于保存可有可无的缓存数据,内存不足时可以被回收,内存充足时用来提高访问速度;

虚引用:必须和引用队列一起使用,它的作用在与跟踪垃圾系统回收过程;

WeakHashMap使用弱引用,可以用作缓存,可以自动释放已经被回收的key所在的表项,但如果key都在系统内持有强引用,那么WeakHashMap就退化为普通的HashMap;

五. 有助于改善性能的技巧

1. try-catch语句对系统性能而言是非常糟糕的,尤其放在循环体内;

2. 调用方法时传递的参数以及在调用中创建的临时变量都保存在栈(Stack)中,速度较快,其他变量,如静态变量,实例变量等,都在堆(Heap)中创建,速度较慢;

3. 尝试使用位运算代替部分算数运算,最典型的就是对于整数的乘除运算优化;

4. 使用数组或枚举类代替Switch语句;

5. 一维数组代替二维数组;

6. 提取表达式,减少重复劳动,尤其是循环体中;

7. 展开循环,减少循环次数,提升系统性能;

int[] array = new int[9999999];
for (int i = 0; i < 9999999; i ++) {
     array[i] = i; // 赋值操作
}

for (int i = 0; i < 9999999; i += 3) { // 展开循环,一个循环体完成3个循环的工作
    array[i] = i;
    array[i+1] = i + 1;
    array[i+2] = i + 2;
}

8. 数组复制,System.arrayCopy()函数是native函数,通常native函数的性能要优于普通的函数;

9. 使用new关键字创建轻量级对象时,速度非常快,但是对于重量级对象,由于对象在构造函数中可能会进行一些复杂且耗时的操作,因此构造函数的执行时间可能会比较长,Object.clone()方法可以绕过对象的构造函数,快速复制一个对象实例,默认情况下,生成的实例只是原对象的浅拷贝,如果需要深拷贝,需要重新实现clone()方法;

10. 由于实例方法需要维护一张类似虚函数表的结构,以实现对多态的支持,与静态方法比,实例方法的调用需要更多的资源,对于一些常用的工具类方法,没有对其进行重载的必要,可以声明为static,调用时也不需要生成类的实例,比调用实例方法更为方便,易用;

Java程序优化

标签:读取   次数   轻量级   需要   遍历   静态方法   一起   dHash   nal   

原文地址:https://www.cnblogs.com/bbbbs/p/12588275.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!