字符串优化处理
字符串的特性:
- 不变性,指一旦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
- 静态方法代替实例方法