`

深入string的substring方法

阅读更多

1.应用举例

        substring方法,例如s="abcdef"  s.substring(2,5)结果为cde,长度为endindex-beginindex

2.实现原理

/**
* Returns a new string that is a substring of this string. The
* substring begins at the specified <code>beginIndex</code> and
* extends to the character at index <code>endIndex - 1</code>.
* Thus the length of the substring is <code>endIndex-beginIndex</code>.
* <p>
* Examples:
* <blockquote><pre>
* "hamburger".substring(4, 8) returns "urge"
* "smiles".substring(1, 5) returns "mile"
* </pre></blockquote>
*
* @param      beginIndex   the beginning index, inclusive.
* @param      endIndex     the ending index, exclusive.
* @return     the specified substring.
* @exception  IndexOutOfBoundsException  if the
*             <code>beginIndex</code> is negative, or
*             <code>endIndex</code> is larger than the length of
*             this <code>String</code> object, or
*             <code>beginIndex</code> is larger than
*             <code>endIndex</code>.
*/
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);
}

        通过源代码可以发现

        a).string内部通过char[]数组实现

        b).substring方法返回了新的string对象,但是string对象却指向原来得char数组,如果原来的string很大,即使原来的string释放,内存空间也无法回收

        c).offset值默认为0,第一个参数为偏移,第二个为长度,第三个为char数组

// 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;
}

        d).默认string构造方法如下:

/**
  * Initializes a newly created {@code String} object so that it represents
  * an empty character sequence.  Note that use of this constructor is
  * unnecessary since Strings are immutable.
  */
public String() {
    this.offset = 0;
    this.count = 0;
    this.value = new char[0];
}

        e).内存泄露测试

package com.bijian.study.string;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

public class StringTest {

	public static void main(String[] args) throws UnsupportedEncodingException {
		
		String aa=new String(new char[100000]);  
        List<String> list=new ArrayList<String>();  
        for (int i = 0; i < 10000000; i++) {  
            //虽然截取的字符串占据空间很小,但是由于aa巨大的数组空间被共享,没有释放,所以内存溢出  
        	//list.add(aa.substring(2, 3));  
            list.add(new String(aa.substring(2,3)));//加一层构造方法后,构造方法内部进行了数组的拷贝,原有的巨大数组空间被回收,不会内存溢出  
        }  
	}
}

        为了避免内存拷贝、加快速度,Sun JDK直接复用了原String对象的char[],偏移量和长度来标识不同的字符串内容。也就是说,substring出的来String小对象仍然会指向原String大对象的char[],split也是同样的情况。这就解释了,为什么HashMap中String对象的char[]都那么大。
原因解释:
        a.程序从每个请求中得到一个String大对象,该对象内部char[]的长度达数百K。
        b.程序对String大对象做split,将split得到的String小对象放到HashMap中,用作缓存。
        c.Sun JDK6对String.split方法做了优化,split出来的Stirng对象直接使用原String对象的char[]
        d.HashMap中的每个String对象其实都指向了一个巨大的char[]
        e.HashMap的上限是万级的,因此被缓存的Sting对象的总大小=万*百K=G级
        f.G级的内存被缓存占用了,大量的内存被浪费,造成内存泄露的迹象
解决方案:
        split是要用的,但是我们不要把split出来的String对象直接放到HashMap中,而是调用一下String的拷贝构造函数String(String original),这个构造函数是安全的,源代码如下:

/**
* Initializes a newly created {@code String} object so that it represents
* the same sequence of characters as the argument; in other words, the
* newly created string is a copy of the argument string. Unless an
* explicit copy of {@code original} is needed, use of this constructor is
* unnecessary since Strings are immutable.
*
* @param  original
*         A {@code String}
*/
public String(String original) {
int size = original.count;
char[] originalValue = original.value;
char[] v;
if (originalValue.length > size) {
    // The array representing the String is bigger than the new
    // String itself.  Perhaps this constructor is being called
    // in order to trim the baggage, so make a copy of the array.
    int off = original.offset;
    v = Arrays.copyOfRange(originalValue, off, off+size);
} else {
    // The array representing the String is the same
    // size as the String, so no point in making a copy.
    v = originalValue;
}
this.offset = 0;
this.count = size;
this.value = v;
} 

文章来源:http://blog.csdn.net/hanruikai/article/details/7479775
分享到:
评论

相关推荐

    Arduino项目开发 Strings_StringSubstring_StringSubstring.pdf

    在本教程中,我们将深入探讨如何使用`substring()`方法来提取`String`对象中的子串。 `substring()`方法主要有两种形式: 1. `substring(index)` 2. `substring(startIndex, endIndex)` 这两种形式都是用来从原始...

    浅谈Java的String中的subString()方法

    本文将深入探讨`substring()` 方法的用法和注意事项。 `substring()` 方法有两种重载形式,一种接受一个参数,另一种接受两个参数。 1. 单参数的 `substring(int index)`: 这个版本的 `substring()` 方法仅接受...

    3种js实现string的substring方法

    在JavaScript中,`substring`方法是String对象的一个内置方法,用于提取字符串中介于两个指定下标之间的字符。为了帮助大家更好地理解和实现这一功能,本文将介绍三种不同的方式来模拟实现`substring`方法。 方法一...

    深入理解Swift中的Substring和String

    在本文中,我们将深入讨论 Swift 中的 Substring 和 String,了解它们的实现原理、特性和使用方法。 一、String 在 Swift 中,String 是一个完整的类型,它有很多特性。String 的实现原理可以通过查看 String....

    java中的String类常用方法解析(一)

    本文将深入解析`String`类的一些常用方法,帮助开发者更好地理解和使用这个核心类。 1. **构造方法** - `String()`:创建一个空字符串。 - `String(char[] value)`:根据字符数组创建字符串。 - `String(String ...

    String类方法总结

    以下是对`String`类中关键方法的深入解读: 1. **charAt(int index)**:此方法允许通过提供一个整数索引来检索`String`中的单个字符。例如,`str.charAt(0)`将返回字符串`str`的第一个字符。 2. **indexOf()系列...

    String方法使用方法例子续--android

    这里我们将深入探讨`String`类的一些重要方法及其在Android开发中的应用。 1. **创建与初始化String对象** - `new String()`: 使用此构造函数创建新的字符串对象。 - `""`: 字符串字面量,如`String str = "Hello...

    JavaScript 和.NET 中substr() 和 substring() 方法的区别

    本文将深入探讨JavaScript中的`substr()`和`.NET`中的`substring()`方法,以及它们之间的区别。 ### JavaScript中的`substr()`方法 在JavaScript中,`substr()`方法用于提取字符串中的一部分。它接受两个参数:...

    char,string全部函数方法说明

    本文将详细介绍`char`和`String`相关的函数方法,帮助新手更好地理解和使用它们。 对于`char`类型,Java提供了一系列静态方法来处理Unicode字符。例如,`charCount(int codePoint)`方法用于计算表示给定Unicode代码...

    java String类常用方法练习小结

    本篇文章将深入探讨`String`类的一些常用方法,并通过实际例子帮助你更好地理解和运用这些方法。 ### 1. 字符串排序 在**字符串练习一**中,我们展示了如何使用`compareTo`方法对字符串数组进行排序。`compareTo`...

    对String的深入理解

    每次修改字符串(如使用`substring`、`concat`或`replace`方法),都会创建一个新的`String`对象。 7. 字符串缓存与intern()方法: `String`类提供了一个`intern()`方法,当调用这个方法时,如果字符串池中已经...

    Java-String类的常用方法总结.pdf

    在这个总结中,我们将深入探讨String类的一些核心特性和方法。 首先,String类位于`java.lang`包中,这意味着它对所有Java程序都是自动导入的,无需额外引用。String类被声明为final,这意味着我们无法创建其子类,...

    关于String类的一些方法

    在本文中,我们将深入探讨`String`类的一些关键方法,这些方法在日常编程中极为常用,有助于字符串的处理和操作。 1. **构造方法**: - `String()`:创建一个空字符串。 - `String(char[] value)`:根据字符数组...

    String类的一些常用方法的测试

    进行测试和编写demo可以帮助开发者深入理解这些方法的运作机制,从而更好地应用到实际项目中。通过创建不同的测试场景,可以全面测试这些方法的各种情况,确保在实际使用时能够正确无误地处理字符串。

    substring.docx

    1. `public String substring(int beginIndex)`:这个版本的`substring`方法从给定的`beginIndex`位置开始,一直截取到字符串的末尾。`beginIndex`是包含在结果子字符串中的第一个字符的位置,索引从0开始。例如,...

    数据库中的substring

    让我们深入探讨一下`substring`在数据库中的应用、功能以及一些相关的编程实践。 `substring`函数的基本语法通常包括三个参数:原始字符串,开始位置和长度。例如,在SQL(结构化查询语言)中,它的基本形式是: `...

    Java的String类

    本文将深入探讨`String`类的各种构造函数、方法及其用途,帮助读者更全面地理解并运用这一关键类。 #### 构造函数 `String`类提供了多种构造函数,以适应不同的初始化需求: 1. **默认构造函数**:`String()` - ...

    String和string区别以及string详解

    本文将深入探讨`String`和`string`的区别,并对`string`类型进行详尽的解释。 首先,`String`和`string`在C#中实际上是指同一个东西,都是System.String类的别名。C#设计者为了提高代码的可读性,推荐在编写代码时...

    深入了解C#的String类.zip

    2. **字符串操作**:`String`类提供了丰富的成员方法,如`Concat`用于连接字符串,`IndexOf`和`LastIndexOf`用于查找子串的位置,`Replace`用于替换子串,`Substring`用于截取子字符串,以及`Trim`和`TrimStart/End`...

Global site tag (gtag.js) - Google Analytics