一个Java字符串过滤函数的性能优化

本文介绍了一种快速过滤字符串中非数字字符的方法,并对比了不同实现方式的性能。通过对多种方法的测试,得出使用字符数组结合StringBuilder进行过滤的效果最佳。

一、需求

  给定一个String对象,过滤掉除数字(字符'0'-'9')以外的其它字符。要求时间开销尽可能小。过滤函数的原型如下: String filter(String str);

 

二、代码测试

 

public static void main(String[] args) {
	String str = "";
	long begin = System.currentTimeMillis();
	for(int i=0;i<1024*1024;i++) {
		str = filter7("D186783E36B721651E8AF96AB1C4000B");
	}
	long end = System.currentTimeMillis();
	System.out.println("测试用时:"+(end-begin));
	System.out.println(str);
}
 

 

三、不同版本

      

        /**
	 * 过滤方法-1-
	 * 测试用时:4328
	 * 运行结果:1867833672165189614000
	 * 注:这种方法效果是最差的,拼接字符串时 起码也要想到StringBuffer或StringBuilder
	 */
	public static String filter1(String str) {
		String newStr = new String();
		for(int i=0;i<str.length();i++) {
			if(str.charAt(i) >= '0' && str.charAt(i) <= '9') {
				newStr +=  str.charAt(i);
			}
		}
		return newStr;
	}
	
	/**
	 * 过滤方法-2-
	 * 测试用时:1656
	 * 运行结果:1867833672165189614000
	 * 注:使用StringBuffer后效率明显提高了
	 */
	public static String filter2(String str) {
		StringBuffer sb = new StringBuffer();
		for(int i=0;i<str.length();i++) {
			if(str.charAt(i) >= '0' && str.charAt(i) <= '9') {
				sb.append(str.charAt(i));
			}
		}
		return sb.toString();
	}
	
	/**
	 * 过滤方法-3-
	 * 测试用时:625
	 * 运行结果:1867833672165189614000
	 * 注:使用StringBuilder后效率也有不错的提升,因为StringBuffer是线程安全的它的方法都是同步的,
	 * 因此调用他的方法有一定的同步开销
	 */
	public static String filter3(String str) {
		StringBuilder sb = new StringBuilder();
		for(int i=0;i<str.length();i++) {
			if(str.charAt(i) >= '0' && str.charAt(i) <= '9') {
				sb.append(str.charAt(i));
			}
		}
		return sb.toString();
	}
	
	/**
	 * 过滤方法-4-
	 * 测试用时:625
	 * 运行结果:1867833672165189614000
	 * 注:循环时就不必每次都计算一下传入的字符串的长度了,但是发现效率没有提升,可能是jdk自己做了优化
	 */
	public static String filter4(String str) {
		StringBuilder sb = new StringBuilder();
		int length = str.length();
		for(int i=0;i<length;i++) {
			if(str.charAt(i) >= '0' && str.charAt(i) <= '9') {
				sb.append(str.charAt(i));
			}
		}
		return sb.toString();
	}
	
	/**
	 * 过滤方法-5-
	 * 测试用时:594
	 * 运行结果:1867833672165189614000
	 * 注:通过StringBuilder的构造函数设置初始的容量大小,可以有效避免append()追加字符时重新分配内存,从而提高性能.
	 */
	public static String filter5(String str) {
		int length = str.length();
		StringBuilder sb = new StringBuilder(length);
		for(int i=0;i<length;i++) {
			if(str.charAt(i) >= '0' && str.charAt(i) <= '9') {
				sb.append(str.charAt(i));
			}
		}
		return sb.toString();
	}
	
	/**
	 * 过滤方法-6-
	 * 测试用时:562
	 * 运行结果:1867833672165189614000
	 * 注:少了个str.charAt(i)提升效果不明显
	 */
	public static String filter6(String str) {
		int length = str.length();
		StringBuilder sb = new StringBuilder(length);
		for(int i=0;i<length;i++) {
			char ch = str.charAt(i);
			if(ch >= '0' && ch <= '9') {
				sb.append(ch);
			}
		}
		return sb.toString();
	}
	
	/**
	 * 过滤方法-7-
	 * 测试用时:406
	 * 运行结果:1867833672165189614000
	 * 注:相比filter6 7里面有字符数组创建的开销, 而StringBuilder也有字符数组创建的开销.
	 *     二者差别就在于7少了StringBuilder对象创建的开销
	 */
	public static String filter7(String str) {
		int length = str.length();
		char[] chArray = new char[length];
		int index = 0;
		for(int i=0;i<length;i++) {
			char ch = str.charAt(i);
			if(ch >= '0' && ch <= '9') {
				chArray[index] = ch;
				index++;
			}
		}
		return new String(chArray,0,index);
	}
 

四、补充

      版本6和版本7使用了空间换时间的手法来提升性能。假如被过滤的字符串很大,并且数字字符的比例很低,这种方式就不太合算了。

   举个例子:被处理的字符串中,绝大部分都只含有不到10%的数字字符,只有少数字符串包含较多的数字字符。这时候该怎么办捏?对于filter6来说,可以把new StringBuffer(nLen);修改为new StringBuffer(nLen/10);来节约空间开销。但是filter7就没法这么玩了。
   所以,具体该用版本6还是版本7,要看具体情况了。只有在你非常看重时间开销,且数字字符比例很高(至少大于50%)的情况下,用filter7才合算。否则的话,建议用filter6。

 

 

 

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值