Java程序性能优化 读书笔记(十五)String类的优化

转载:String,StringBuffer与StringBuilder的区别??

一、String对象的内存分布

对于如下代码:

String str1 = "hello";
String str2 = new String("hello");

第一种方法:引用str1被存放在栈区,字符串常量"hello"被存放在常量池,引用str1指向了常量池中的"hello"(str1中的存放了常量池中"hello"的地址)。

第二种方法:引用str2被存放在栈区,同时在堆区开辟一块内存用于存放一个新的String类型对象。(同上,str2指向了堆区新开辟的String类型的对象)


而对于如下代码:

String str1 = "hello";
String str2 = "hello";
str1和str2均指向常量池中的“hello”常量:


对于如下代码:

String str1 = new String("hello");
String str2 = new String("hello");

str1和str2指向不同的内存对象



二、字符串分割和查找的效率问题

字符串的分割可以采用三种方式完成:

1. 使用split函数

split 的实现直接调用的 matcher 类的 split 的方法。在使用String.split方法分隔字符串时,分隔符如果用到一些特殊字符,可能会得不到我们预期的结果。在正则表达式中有特殊的含义的字符,我们使用的时候必须进行转义

1.字符"|","*","+"都得加上转义字符,前面加上"\\"。

2.而如果是"\",那么就得写成"\\\\"。

3.如果一个字符串中有多个分隔符,可以用"|"作为连字符。

比如:String str = "Java string-split#test",可以用Str.split(" |-|#")把每个字符串分开。这样就把字符串分成了3个子字符串。

public class StringSplit {  
    public static void main(String[] args) {  
        String value = "192.168.128.33";  
        // 注意要加\\,要不出不来,yeah  
        String[] names = value.split("\\.");  
        for (int i = 0; i < names.length; i++) {  
            System.out.println(names[i]);  
        }  
    }  
}  

2. 使用StringTokenizer

StringTokenizer类:根据自定义字符为分界符进行拆分,并将结果进行封装提供对应方法进行遍历取值, StringTokenizer 方法不区分标识符、数和带引号的字符串,它们也不识别并跳过注释;该方法用途类似于split方法,只是对结果进行了封装;StringTokenizer 是出于兼容性的原因而被保留的遗留类,并不鼓励使用。

        impoort java.util.*;
        public class StringTokenizer Demo 
        { 
              public static void main(String[] args)
              { 
                  String str=" hello,java,delphi,asp,php";
                  StringTokenizer st=new StringTokenizer(str,",");
                  while(st.hasMoreTokens()) { 
                      System.out.println(st.nextToken());
                  }
              }
         } 

3. 使用indexof和subString

indexof和subString都是执行很快的方法,下面代码可以实现字符串的拆分:

String tmp = orgstr;
while(true){
	String splitStr = null;
	int j = tmp.indexof(';');
	if (j < 0) {
		break;
	}
	splitStr = tmp.subString(0, j);
	tmp = tmp.subString(j+1);
}

效率比较

String.split(String.split是用正则表达式匹配,所以不使用KMP字符串匹配算法)用的都是按顺序遍历的算法,时间复杂度O(m*n),较高,所以性能上,StringTokenizer好很多,对于频繁使用字符串分割的应用,使用StringTokenizer性能可以提高很多。完全由indexof和subString实现的函数效率最好。


三、String/StringBuffer/StringBuilder的效率

三者在执行速度方面的比较:StringBuilder >  StringBuffer  >  String

1.String是“字符串常量”,也就是不可改变的对象。每次对其进行的操作都等于生成了一个新的String变量

2.StringBuffer是字符串变量(线程安全),StringBuffer是一个类似于 String 的字符串缓冲区,但不能修改。虽然在任意时间点上它都包含某种特定的字符序列,但通过某些方法调用可以改变该序列的长度和内容。StringBuffer 上的主要操作是 append insert 方法,可重载这些方法,以接受任意类型的数据。append 方法始终将这些字符添加到缓冲区的末端;而 insert 方法则在指定的点添加字符。

3.StringBuilder是字符串变量,非线程安全。StringBuilder一个可变的字符序列,此类提供一个与 StringBuffer 兼容的 API,但不保证同步。该类被设计用作 StringBuffer 的一个简易替换,用在字符串缓冲区被单个线程使用的时候(这种情况很普遍)。如果可能,建议优先采用该类,因为在大多数实现中,它比 StringBuffer 要快。两者的方法基本相同。





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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值