字符串优化处理


字符串的特性:
  • 不变性,指一旦String对象生成,则不能再对它进行改变。主要应用一个对象被多线程共享,并且频繁访问时,可以省略同步和锁等待时间,从而大幅提高系统性能
  • 常量池的优化,当两个String对象拥有相同的值时,它们只引用常量池中的一个拷贝,当同一个字符串反复出现,这个技术可以节省空间
  • 类的final定义,不可能拥有任何子类,对系统安全性的保护
分割字符串使用StringTokenizer类强于传统的split(";")
StringTokenizer st=new StringTokenizer(orgStr,";");
for(int i=0;i<1000;i++){
    while(st.hasMoreTokens()){
        st.nextToken();
    }
    st=new StringTokenizer(orgStr,";");
}
如果使用indexOf(),subString()的算法性能远远超过split(),StringTokenizer,适合作为高频函数使用。
StringBuffer和StringBulider:
由于String对象是不可变对象,因此在对字符串进行修改操作时(连接、替换),总会生出新的对象,性能会变差,所以JDK提供了用于创建和修改的字符串工具。
StringBuffer对所有的方法做了同步,而StringBuilder并没有做任何同步。因此StringBuilder效率好于StringBuffer,但是多线程系统中StringBuilder无法保证线程安全。

核心数据结构

List的实现:ArrayList  Vector  LinkedList

ArrayList和Vector使用了数组实现,封装了对数组的操作(添加、删除、插入……)唯一的区别就是ArrayList没有对任何一个方法做线程同步,在多线程环境下线程是不安全的。
Vector绝大部分方法使用了线程同步,是一种线程安全的实现。
LinkedList使用了循环双向链表
总而言之:如果在系统中经常在任意位置插入元素,则用LinkedList代替ArrayList

Map接口

Hashtable大部分方法做了同步,而HashMap没有,所以HashMap不是线程安全的。
HashMap的无序性,LinkedHashMap的有序性

使用NIO提升性能

..I/O的速度要比内存的速度慢,因此I/O会成为系统瓶颈。
InputStream和OutputStream这两种基于字节为单位处理数据,并且非常容易建立各种过滤器。

NIO是New I/O的简称,具有特性:(与传统的流式I/O不同,NIO是基于Block为基本单位处理数据)

  • 为所有的原始类提供Buffer缓存支持
  • 使用Java.nio.charset.Charset作为字符集编码解码解决方案
  • 增加通道Channel对象,作为新的原始I/O抽象
  • 支持锁和内存映射文件的文件访问接口
  • 提供了基于Selector的一部网络I/O

/**
    应用程序不能直接对Channel进行读写操作,必须通过Buffer来进行。
    比如在读一个Channel的时候,需要先将数据读入到相应的Buffer,然后在Buffer中进行读取
*/
FileInputStream fin=new FileInputStream(new File("d:\\buffer.tmp"));
FileChannel fc=fin.getChannel();
ByteBuffer byteBuffer=ByteBuffer.allocate(1024);
fc.read(byteBuffer);

fc.close();
byteBuffer.filp();

//之后,就可以从ByteBuffer中取得文件内容

文件的复制(NIO的读写)


Bufferde创建:

  • ByteBuffer buffer=ByteBuffer.allocate(1024);  //从堆中分配
  • byte array[]=new byte[1024];  ByteBuffer buffer=ByteBuffer.wrap(array); //从既有数组中创建
重置和清空缓冲区:
  • rewind()将position置零,并清除标志位,
out.write(buf);  //从Buffer 读取数据写入Channel
buf.rewind();    //回滚Buffer
buf.get(array);  //将Buffer的有效数据复制到数组中
  • clear()也将position置零,同时将limit设置为capcity的大小并清除mark,由于清空了limit,因此无法得知Buffer内哪些数据真实有效。
  • buf.clear();   //为读入数据到Buffer做准备
    in.read(buf);  //从通道读入数据
    flip()先将limit设置到position所在位置,然后将position置零,并清除标志位mark,读写转换时使用。
  • buf.put(magic); //将magic数组写入Buffer
    in.read(buf);  //从通道读入给定信息,存放到Buffer中
    buf.flip();  //将Buffer从写状态转换为读状态
    out.write(buf); //将magic和in通道中读入的信息,写到通道out中

标志缓冲区,复制缓冲区,缓冲区分片,只读缓冲区(数据安全)
文件映射到内存,处理结构化数据(散射,聚集)

引用类型

  • 强引用:可以直接访问目标对象,所指向的对象在任何时候都不会被系统回收,JVM宁愿抛出OOM异常,可能导致内存泄漏。
  • 软引用:通过java.lang.ref.SoftReference使用软引用。JVM会根据当前堆的使用情况来判断何时回收,当堆使用频率接近阀值时,才会回收。只要有足够的内存,软引用可能在内存中存活相当长一段时间。
  • 弱引用:GC时只要发现弱引用就会将对象进行回收,但由于垃圾回收器的线程通常优先级很低,因此并不一定很快地发现斥候弱引用的对象。一旦一个弱引用对象被垃圾回收器回收,便会加入到一个注册引用队列中。
  • 虚引用:作用在于跟踪垃圾回收过程,当垃圾回收器准备回收一个对象时,如果发现它还有虚引用,就在垃圾回收后销毁这个对象时,就将这个虚引用加入引用队列。

其他

  • 慎用异常:try/catch应用于循环体之中的耗费性能远远大于循环体外。
  • 局部变量:在函数体内定义局部变量的耗时小于静态变量的定义。
  • 位运算代替乘除运算:a<<=1(乘以2);  a>>=1(除以2)
  • 一维数组代替二维数组:
  • 布尔值代替位运算:
  • 使用arrayCopy()
  • 使用clone()代替new 
  • 静态方法代替实例方法