substring()字节字符截取两种方式及内存泄漏问题,substring两种方式
substring()字节字符截取两种方式及内存泄漏问题,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
===================================================================================================
相关文章
- 暂无相关文章
用户点评