串的基本概念
串(也称作字符串)是由n(n≥0)个字符组成的有限序列。
一个串中任意个连续的字符组成的子序列称为该串的子串。 包含子串的串称为该子串的主串。
一个字符在一个串中的位置序号(为大于等于0的正整数)称为该字符在串中的位置。当且仅当这两个串的值完全相等时,称这两个串相等。
串抽象数据类型
数据集合:串的数据集合可以表示为字符序列s0, s1,… , sn-1,每个数据元素的数据类型为字符类型。
操作集合:
(1)取字符charAt(index) :取index下标的字符返回。
(2)求长度length():返回串的长度。
(3)比较compareTo(anotherString):比较当前对象串和串anotherString的Unicode码值的大小。
(4)取子串substring(beginIndex,endIndex):取当前对象串中从beginIndex下标开始、至endIndex下标的前一下标止的子串。
(5)连接concat(str):把串str连接到当前对象串的末尾。
(6)插入子串insert(str, pos):在当前对象串的第pos个字符前插入子串str。
(7)删除子串delete(beginIndex,endIndex):删除当前对象串中从beginIndex下标开始、至endIndex下标的前一下标止的子串 。
(8)输出串值myPrint():输出当前对象的串值。
//建议重写Object类的toString()方法。使用toString()代替
(9)查找子串index(subStr,start):在当前对象串的start下标开始,查找是否存在子串subStr。
串的存储结构
}串的顺序存储结构
串的顺序存储结构就是用字符类型数组存放串的所有字符。表示串的长度通常有两种方法:
(1)设置一个串的长度参数。
(2)在串值的末尾添加结束标记。
串值长度的第一种表示方法下,串的成员变量应包括如下两项:
char[] value;
int count;
其中,value为存储串值的字符类型数组名,count表示串值的长度。
设计MyString类
//用户自定义的MyString类 public class MyString { private char[] value; //字符数组 private int count; //字符串的长度 //从源串指定下标开始拷贝指定长度的字符串到目标串指定为下标开始 //char[] src:源串 //int srcPos:源串的开始下标 //char[] dst:目标串 //int dstPos:目标串开始下标 //int length:拷贝长度 public static void arrayCopy(char[] src,int srcPos,char[] dst,int dstPos,int length) { //如果源串起始下标+拷贝长度>源串长度或者目标串起始下标+拷贝长度>目标串长度 if(srcPos+length>src.length||dstPos+length>dst.length) { throw new StringIndexOutOfBoundsException(length); } for(int i=0;i<length;i++) { dst[dstPos++]=src[srcPos++]; } } //构造方法1,构造一个空字符串 public MyString() { value=new char[0]; count=0; } //构造方法2,实现从一个字符数组中提取出新的字符串。 //char[] value:已有的字符数组。 //int offset:起始下标 //int count:拷贝的个数 public MyString(char[] value,int offset,int count) { //判断起始位置是否<0 if(offset<0) { throw new StringIndexOutOfBoundsException(offset); } //判断count是否<0 if(count<0) { throw new StringIndexOutOfBoundsException(count); } //判断起始位置+count是否大于value字符串的长度 if(offset+count>value.length) { throw new StringIndexOutOfBoundsException(offset+count); } this.value = new char[count]; this.count = count; arrayCopy(value,offset,this.value,0,count); } //构造方法3,根据已有的字符数组,构造新的字符串 public MyString(char[] value) { this.count = value.length; this.value = new char[count]; arrayCopy(value,0,this.value,0,count); } //构造方法4,使用JDK本身的String类,构造新的字符串 public MyString(String str) { char[] chararray = str.toCharArray(); value = chararray; count = chararray.length; } @Override public String toString() { // TODO Auto-generated method stub String str=""; for(int i=0;i<count;i++) { str+=value[i]; } return str; } public int length() { return count; } public char charAt(int index) { if(index<0||index>=count) { throw new StringIndexOutOfBoundsException(index); } return value[index]; } //比较两个字符串的大小 //如果当前字符串大于比较字符串,返回一个正整数 //如果当前字符串等于比较字符串,返回0 //如果当前字符串小于比较字符串,返回负整数 public int compareTo(MyString anotherStr) { int len1= this.count; int len2 = anotherStr.length(); int n = Math.min(len1, len2); char[] v1 = value; char[] v2 = anotherStr.value; int i=0; while(i<n) { char c1 =v1[i]; char c2 =v2[i]; if(c1!=c2) { return c1-c2; } i++; } return len1-len2; } //求子串1,给出起始下标 public MyString 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 MyString(value,beginIndex,endIndex-beginIndex); } //求子串2,给出开始下标,到字符串末尾 public MyString substring(int beginIndex) { return substring(beginIndex,count); } public char[] toCharArray() { char[] buff = new char[count]; arrayCopy(value,0,buff,0,count); return buff; } //字符串的连接 public MyString concat(MyString str) { int otherLen = str.length(); char[] strarray = str.toCharArray(); if(otherLen==0) { return this; } char[] buff = new char[count+otherLen]; arrayCopy(value,0,buff,0,count); arrayCopy(strarray,0,buff,count,otherLen); return new MyString(buff); } //插入子串 public MyString insert(MyString str,int pos) { if(pos<0||pos>count) { throw new StringIndexOutOfBoundsException(pos); } if(pos!=0) { //获得插入点之前的子串 MyString str1 =this.substring(0, pos); //获得插入点之后的子串 MyString str2 = this.substring(pos); MyString res1 = str1.concat(str); MyString res2 = res1.concat(str2); return res2; } else { return str.concat(this); } } //删除子串 public MyString delete(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); } //删除整个字符串 if(beginIndex==0&&endIndex==count) { return new MyString(); } else { //获得删除点前的子串 MyString str1 = this.substring(0,beginIndex); //获得删除子串后的子串 MyString str2 = this.substring(endIndex); return str1.concat(str2); } } }
public class Test { /** * @param args */ public static void main(String[] args) { // TODO Auto-generated method stub char[] c1={'c','h','i','n','a'}; char[] c2={'I','l','o','v','e',' ','c','h','i','n','a'}; //构造方法1 MyString str1= new MyString(); //构造方法3 MyString str2 = new MyString(c1); //构造方法2 MyString str3 = new MyString(c2,1,5); //构造方法4 MyString str4 = new MyString("Hello "); MyString str5 = new MyString("China"); System.out.println(str1); System.out.println(str2); System.out.println(str3); System.out.println(str4); System.out.println(str4.length()); System.out.println(str3.charAt(2)); System.out.println(str5); System.out.println(str5.hashCode()); str5 =str5.concat(str4); System.out.println(str5); System.out.println(str5.hashCode()); } }