substring()字节字符截取两种方式及内存泄漏问题

substring()或者substr()是大部分主流语言所支持的,同时对字符串的操作是编程中最频繁的操作,当然对截取字符串也是最常用操作之一。所以今天就讨论一下subtring()。

以JAVA举例,在JAVA中我们看看系统提供的substring()有什么问题?

我们首先看看JDK中substring()的源码:

   public String substring(int beginIndex, int endIndex) {
	if (beginIndex < 0) {
	    throw new StringIndexOutOfBoundsException(beginIndex);
	}
	if (endIndex > count) {
	    throw new StringIndexOutOfBoundsException(endIndex);
	}
	if (beginIndex > endIndex) {
	    throw new StringIndexOutOfBoundsException(endIndex - beginIndex);
	}
	return ((beginIndex == 0) && (endIndex == count)) ? this :
	    new String(offset + beginIndex, endIndex - beginIndex, value);
    }

这段代码主要的这行:new String(offset + beginIndex, endIndex - beginIndex, value)

我们在进这个String构造方法,看看它做了什么?

    // Package private constructor which shares value array for speed.
    String(int offset, int count, char value[]) {
	this.value = value;
	this.offset = offset;
	this.count = count;
    }

我们发现惊奇的发现JDK源码中很少有对一个函数进行单行注释,这里居然出现了,肯定是作者尤其强调的,用博主“拙劣”的英文水平帮着翻译下它的意思:私有构造器共享着value数组为了去提高效率。接下来我们看看这个String构造函数,我们发现它在截取字符串的时候创造一个String对象但是引用了原来的char value[],利用偏移量的方式达到一个截取的效果,我们并不需要原来的字符串了,但JVM通过扫描发现原来的String的对象还有引用指向它,所以不能回收。这就造成了内存泄漏。

PS:JDK7版本已解决上诉问题,感兴趣的朋友可以去看源码。

所以当对内存要求高的时候,或者需要提高软件寿命,我们需要对它进行处理,博主在这里提供两种方法:

方式一:既然截取后的字符串引用指向原来的对象,我们当然可以让这个子字符串自己独占一个对象,原来的字符串就可以被回收了。

比如String newStr = s.substring(1,3); 改成String newStr = new String(s.substring(1,3));

方式二:我们大可自己写一个substring()函数

代码清单:

public class MySubString {
	
	public static void main(String[] args) {

		String s = "人在江湖,记录那些有趣的事";
		System.out.println(substring(s, 2, 4));
		System.out.println(substring(s, 2));

	}

	public static String substring(String s, int begin, int end) {
		if(null == s || "".equals(s))
			return null;
		if (begin < 0 || end > s.length() || end - begin < 0)
			return null;
		char[] cs = s.toCharArray();
		char[] new_cs = new char[end - begin];//待返回的字符数组
		int index = 0;
		for (int i = begin; i < end; i++) {
			new_cs[index++] = cs[i];
		}
		return new String(new_cs);
	}

	public static String substring(String s, int begin) {
		return substring(s, begin,s.length());
	}

	
}


有的语言比如像PHP,它的截取字符串函数substr()函数是按字节截取的,我们知道在不同编码下,一个汉字所占 字节数是不同的,所以用它截取中文可能会产生乱码,所以这种情况下用字符截取方便的多(PHP中iconv_substr()是按字符截取的),但也有很多情况需要用到字节截取,但我们知道JAVA的字符串是按字符截取的,它并没有字节截取的函数,所以我们有时得自己写按字节截取的substring()

代码清单:

public class MySubString {
	
	public static void main(String[] args) {

		String s = "人在江湖,记录那些有趣的事";
		System.out.println(subStringByByte(s, 2, 4));
		System.out.println(subStringByByte(s, 2));

	}


	public static String subStringByByte(String s, int begin, int end) {
		
		if(null == s || "".equals(s))
			return null;
		if (begin < 0 || end > s.getBytes().length || end - begin < 0)
			return null;
		byte[] bs = s.getBytes();
		byte[] new_bs = new byte[end-begin];
		int index = 0;
		for(int i = begin; i < end; i++){
			new_bs[index++] = bs[i];
		}
		return new String(new_bs);

	}
	public static String subStringByByte(String s, int begin) {
		return subStringByByte(s, begin, s.getBytes().length);
	}

	
}


==================================================================================================

作者:nash_ 欢迎转载,与人分享是进步的源泉!

转载请保留原文地址http://blog.csdn.net/nash_/article/details/8282525

===================================================================================================

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值