java 字符串处理流程_1.Java程序优化-字符串优化处理

String对象及其特点

String并不是Java的基本数据类型,从String的代码实现来说,它主要包括三个部分:char数组,偏移量和String的长度。char数组表示String的内容,它是String对象所表示的字符串的超集。String的真实内容还需要由偏移量和长度在这个char数组中进行定位和截取。       String对象具有三个基本特点:       不变性:String对象一旦生成,就不能修改它了。String的这个特性可以泛化为不变模式(一种设计模式),即一个对象的状态在被创建后就不再发生变化。不变模式的主要作用在于当一个对象需要被多线程共享,并且访问频繁时,可以省略同步和锁等待时间,从而大幅度提高系统性能。       针对常量池的优化:当两个String对象拥有相同的值时,它们只引用常量池中的同一个拷贝。当同一个字符串反复出现时,这个技术可以大幅度节省内存空间。

String str1="abc";

String str2="abc";

String str3=new String("abc");

System.out.println(str1==str2);          //返回true

System.out.println(str1==str3);          //返回false

System.out.println(str1==str3.intern()); //返回true,使用intern()方法返回该String对象在常量池中的引用

str1和str2引用了相同的地址,但是str3却重新开辟了一块内存空间。但即便如此,str3在常量池中的位置和str1是一样的,也就是说,虽然str3单独占用了堆空间,但是它所指向的实体却和str1完全一样。

类的final定义:作为final类的String不会有任何子类,这是对系统安全性的保护。同时,对于JDK1.5之前的环境中,使用final定义,有助于帮助虚拟机寻找机会,内联所有的final方法,从而提高系统效率。但这种优化方法在JDK1.5之后,效果并不明显。

subString()方法的内存泄漏

截取子字符串是非常常见的操作之一,String提供了两种截取子字符串的方法:

public String subString(int beginIndex);

public String subString(int beginIndex,int endIndex); //从beginIndex开始,到endIndex为止的子字符串;这个方法存在严重的内存泄漏问题

//上述第二个方法的源码实现

public String substring(int beginIndex, int endIndex) {

if (beginIndex < 0) {

throw new StringIndexOutOfBoundsException(beginIndex);

}

if (endIndex > value.length) {

throw new StringIndexOutOfBoundsException(endIndex);

}

int subLen = endIndex - beginIndex;

if (subLen < 0) {

throw new StringIndexOutOfBoundsException(subLen);

}

//上面的代码都是为了检查是否越界的,不重要

//如果要返回的子字符串是字符串本身就直接返回字符串本身

//如果不是,返回一个新建的String对象

return ((beginIndex == 0) && (endIndex == value.length)) ? this

: new String(value, beginIndex, subLen);

}

//subString()方法最后调用的String构造方法

String(int offset,int count,char value[]){

//String原生内容value数组被复制到新的子字符串中,通过偏移量和长度来截取字符串

this.value = value;

this.offset = offset;

this.count = count;

}

//试想一下,如果原始字符串很大,截取的字符串却很短,

//那么生成后的子字符串包含了原生字符串的所有内容,并占据了相应的内存空间,

//而仅仅通过偏移量和长度来决定实际的取值

//这种做法提高了运算速度却浪费了大量的内存空间

//这是新版本的JDK中的构造方法,更改了,解决了内存泄漏的问题

public String(char value[], int offset, int count) {

if (offset < 0) {

throw new StringIndexOutOfBoundsException(offset);

}

if (count <= 0) {

if (count < 0) {

throw new StringIndexOutOfBoundsException(count);

}

if (offset <= value.length) {

this.value = "".value;

return;

}

}

// Note: offset or count might be near -1>>>1.

if (offset > value.length - count) {

throw new StringIndexOutOfBoundsException(offset + count);

}

//上面代码部分都是为了检查是否越界的问题

this.value = Arrays.copyOfRange(value, offset, offset+count);

}

字符串分割和查找

字符串分割将一个原始字符串,根据某个分割符,切割成一组小字符串。String的split()方法就实现了该方法;

public String[] split(String regex)  //regex可以是一个普通一个正则表达式,从而进行复杂逻辑的字符串分割

比如字符串“a;b,c:d”,如果要把这些分隔符去掉,只保留字母内容,只需要使用正则表达式“[;|,|:]"。就简单的字符串分割而言,spilt()方法的性能却不太好。

最原始的字符串分割

直接使用split()方法对字符串进行分割,是最原始的方法。String.split()方法使用简单,功能强大。但是在频繁地使用该方法,性能比较差。

使用效率更高的StringTokenizer类分割字符串

StringTokenizer是JDK中专门用来处理字符串分割成子串的工具类。

//构造函数

public StringTokenizer(String str,String delim)  //str为要被分割处理的字符串,delim是分割字符

StringTokenizer st = new StringTokenizer(orgStr,";");

for(int i=0;i<10000;i++){

while(st.hasMoreTokens()){  //知道是否有更多的子字符串需要处理

st.nextToken();         //得到下一个分割的字符串

}

st = new StringTokenizer(orgStr,";"); //这说明使用上述两个方法会改变st对象本身的值,所以需要重新赋值

}

更优化的字符串分割方式

//indexOf()和subString()这两个方法的执行效率非常高,很适合作为高频率的函数使用

String tmp = orgStr;

for(int i=0;i<10000;i++){

while(true){

String splitStr=null;

int j=tmp.indexOf(';');  //找分割符的位置

if(j<0) break;           //没有分割符存在

splitStr=tmp.subString(0,j); //找到了分割符,截取前面的子字符串

tmp=tmp.subString(j+1);      //剩下的需要处理的字符串

}

tmp=orgStr;

}

高效率的charAt()方法

//String提供的方法

//返回给定的字符串中,位置在index位置的字符

//功能与indexOf()相反,但效率和indexOf()一样高

public char charAt(int index)

//下面的两个方法的效率远低于charAt()方法

//判断字符串是否以prefix字符串开头

public boolean startWith(String prefix)

//判断字符串是否以suffix结尾

public boolean endWith(String suffix)

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值