620 likes | 773 Views
第四章 数组与字符串. 浙江工业大学 计算机学院 赵小敏 zxm@zjut.edu.cn http://211.155.231.249:8009. 主要内容. 数组 数组的应用 字符串 String 可变字符序列 StringBuffer 可变字符序列 StringBuilder. 4.1 数组. 数组是相同类型的数据元素按顺序组成的一种复合数据类型,元素在数组中的相对位置由下标来指明。 例如 :public static void main(String args []) 其中 args 是 String 类型的数组 占用连续的内存地址 数组的静态性
E N D
第四章 数组与字符串 浙江工业大学 计算机学院 赵小敏 zxm@zjut.edu.cn http://211.155.231.249:8009
主要内容 • 数组 • 数组的应用 • 字符串String • 可变字符序列StringBuffer • 可变字符序列StringBuilder
4.1 数组 • 数组是相同类型的数据元素按顺序组成的一种复合数据类型,元素在数组中的相对位置由下标来指明。 • 例如:public static void main(String args[]) 其中args是String类型的数组 • 占用连续的内存地址 • 数组的静态性 • 一旦创建就不能修改数组的长度
数组声明 • 一维数组变量的声明格式有如下两种: (1) 数组元素的数据类型 [ ] 变量名; (2) 数组元素的数据类型 变量名 [ ]; • 示例: int [ ] c; String[ ] names; int c[ ]; String names[ ];
数组的实例化 • Java数组实际上也是对象,所以可通过new关键字来创建。 • 示例: int[ ] c;// 声明,不必指定数组的大小 c =newint[12];// 创建对象,并分配内存 上面的两个语句可以简化成一个语句: int[ ] c = newint[12]; • 数组的长度用数组名.length,如c.length • 数组元素用数组名[下表]表示,下标的范围是0~数组长度-1,如c[0]
初始化数组 • 基本数据类型的元素初始化为0值或false • 非基本数据类型的元素初始化为null • 可以采用循环结构初始化数组 • 示例: double[ ] squares; squares = new double[100]; for (int i=0; i < squares.length; i++){ squares[i] = i*i; }
通过初始化语句创建数组 • Java语言允许通过数组的初始化语句创建数组 • 示例: int[ ] n = { 10, 20, 30, 40, 50 }; • 上面语句创建了一个含有五个元素的数组 • 下标值分别为0, 1, 2, 3, 4 • 这时不需要运算符new
数组的注意事项 • 当通过循环遍历数组时 • 下标永远不要低于0 • 下标永远要比数组元素个数小 • 当数组下标出错,Java 产生 ArrayIndexOutOfBoundsException异常 • 数组一旦创建后,不能调整大小 • 可使用相同的引用变量来引用一个全新的数组 int []a = new int[6]; a = new int[10];
a[ 0 ][ 0 ] a[ 1 ][ 0 ] a[ 2 ][ 0 ] a[ 0 ][ 1 ] a[ 1 ][ 1 ] a[ 2 ][ 1 ] a[ 0 ][ 2 ] a[ 1 ][ 2 ] a[ 2 ][ 2 ] a[ 0 ][ 3 ] a[ 1 ][ 3 ] a[ 2 ][ 3 ] 多维数组 • 最常用的多维数组是二维数组 int[ ][ ] a = newint[3][4]; • 二维数组可以理解成如下图示的表格 行的下标值 列的下标值
二维数组的创建(内存分配) (1)直接为每一维分配空间,如: inta[ ][ ] = newint[2][3]; • 该语句创建了一个二维数组a,其较高一维含两个元素,每个元素为由3个整型数构成的整型数组。 • 此时该数组的元素为: a[0][0] a[0][1] a[0][2] a[1][0] a[1][1] a[1][2]
二维数组的创建(内存分配) (2)从最高维开始,分别为每一维分配空间 • 二维数组的实际上是数组的数组,即创建以数组为元素的数组,意味着: 二维数组的每一行可以具有不同的列数,如: intb[ ][ ] = new int[2][ ]; // 最高维含2个元素,每个元素为一个整型数组 b[0] = new int[3]; b[1] = new int[5]; 此时该数组的元素为: b[0][0] b[0][1] b[0][2] b[1][0] b[1][1] b[1][2] b[1][3] b[1][4]
二维数组元素的初始化 (1)先创建二维数组,然后通过循环直接对每个元素进行赋值,如: int[ ][ ] matrix = new int[4][5]; for (int row=0; row < matrix.length; row++){ for (int col=0; col < matrix[row].length; col++){ matrix[row][col] = row + col; } } 注:二维数组的长度指的是二维数组的行数,用数组名.length表示,某i行的数组长度(该行的列数)用数组名[i].length表示
二维数组元素的初始化 (2)在声明数组的同时进行初始化。如: int a[ ][ ]={{2,3},{1,5},{3,4}}; 声明了一个3×2的数组,并对每个元素赋值,即: a[0][0] = 2 a[0][1] = 3 a[1][0] = 1 a[1][1] = 5 a[2][0] = 3 a[2][1] = 4
例:构造杨辉三角形 • class Yanghui{ • public static void main(String[] args){ • int yanghui[ ][ ]={{1},{1,1},{1,2,1},{1,3,3,1}, {1,4,6,4,1}}; • for(int i=0;i<yanghui.length;i++){ • for(int j=0;j<yanghui[i].length;j++){ • System.out.print("\t"+yanghui[i][j]); • } • System.out.println(); • } • } • }
4.2数组的应用 • 复制数组 • 数组的封装类Arrays • 数组用作参数和返回值 • main方法的数组参数获取命令行输入
复制数组 • Java在System类中提供了一个特殊的方法arraycopy(),用于实现数组之间的复制 • public class ArrayCopy{ • public static void main(String args[]){ • int i; • int arr1[]={1,2,3,4,5,6,7,8,9,10}; • int arr2[]=new int[10]; • //把arr1中所有元素复制到arr2中,下标从0开始 • System.arraycopy(arr1,0,arr2,0,arr1.length); • for(i=0;i<arr2.length;i++) • System.out.print(arr2[i]+" "); • System.out.println(); • } • }
数组的封装类Arrays • java.util包封装了一个Arrays类,可实现数组操作的查找、复制和排序 • binarySearch(int[] a, int fromIndex, int toIndex, int key) • copyOf(int[] original, int newLength) • copyOfRange(int[] original, int from, int to) • sort(int[] a)
例:数组元素排序 • import java.util.Arrays; • public class ArraySort { • public static void main(String []args){ • int []hold={10,1,8,3,6,5,4,7,2,9}; • Arrays.sort(hold); • for(int i=0;i<hold.length;i++){ • System.out.print(hold[i]+" "); • } • } • }
数组用作参数和返回值 • 数组可以作为参数传递给方法,也可以作为方法的返回值 • 在调用的方法中的数组对象与调用者中的是同一个。 • 如果在方法中修改了任何一个数组元素,因为这个数组与方法之外的数组对象是同一个,所以方法之外的数组也将发生改变。
例:数组作为调用方法的传递参数 • public class CallArray{ • static void updateArray (int[ ] arrays){ • arrays[3]=10; • } • public static void main(String []args){ • int [ ]hold={0,1,2,3,4,5,6,7,8,9}; • updateArray(hold); • for(int i=0;i<hold.length;i++){ • System.out.print(hold[i]+" "); • } • } • } 运行时,hold数组的内容如下: 0,1,2,10,4,5,6,7,8,9
例:数组作为方法的返回结果 • public class ReturnArray{ • static int[ ] updateArray(int[] arrays){ • for(int i=0;i<arrays.length;i++){ • arrays[i]=i; • } • return arrays; • } • public static void main(String []args){ • int [ ]hold={9,8,7,3,5,6,4,2,1,0}; • hold= updateArray(hold); • for(int i=0;i<hold.length;i++){ • System.out.println("hold["+i+"]="+hold[i]); • } • } • }
main方法的数组参数获取命令行输入 • 在Java程序的主方法public static void main (String args[ ]) 中,args[ ]是一个字符串数组,用来接收应用程序被调用时由用户直接从键盘输的参数。 例:应用程序被调用时参数的传递 public class MyFriend{ public static void main (String arg[]){ System.out.println(arg[0]+ "and"+ arg[1] +"are my good friends! "); } } • 程序经编译后,采用命令java MyFriend Tom Alice来执行 • 程序运行结果为: Tom and Alice are my good friends!
String name; name = new String( “Latte” ); String name; name = “Latte”; 4.3 字符串String • 在Java中字符串是对象,用String类来创建 • 在Java中对字符串的处理,需要事先创建一个String的实例,即像其它对象一样,需要对String声明和实例化, 如: 但我们也可以用简写的形式,像基本数据类型一样创建String ,如:
String对象 • 与C语言不同: 字符(char)数组不是字符串(String),String数值不必以'\u0000'结束 • String对象一旦被创建后就不能被改变,称为非可变对象
String的构造方法 • String() • String(byte[] bytes) • String(byte[] bytes, Charset charset) • String(byte[] bytes, int offset, int length) • String(byte[] bytes, int offset, int length, Charset charset) • String(byte[] bytes, int offset, int length, String charsetName) • String(byte[] bytes, String charsetName) • String(char[] value) • String(char[] value, int offset, int count) • String(int[] codePoints, int offset, int count) • String(String original) • String(StringBuffer buffer) • String(StringBuilder builder)
String s1=“hello”; String s2=“hello”; String s3=new String(“hello”); String s4=new String(“hello”); String对象的创建
String s1=“hello”; String s2=“hello”; s1 hello hello s2 String Tom String对象的内存分配 字符串池 John Java World JVM 堆内存
String s3=new String(“hello”); String s4=new String(“hello”); String String hello hello s3 String Tom s4 String对象的内存分配(续) 字符串池 John Java World hello s1 s2 JVM 堆内存
s1=s1+“ world”; String String Tom hello world s1 String对象的内存分配(续) 字符串池 John String Java hello s3 World String s1 hello s2 hello s4 JVM 堆内存
String类的方法及应用 • 字符串长度 • 比较字符串 • 连接字符串 • 拷贝字符串 • 搜索字符 • 搜索子串 • 修改字符串 • 其他方法
编译错误 7 3 0 name.length( ); str1.length( ); str2.length( ); str3.length( ); String name = “Sumatra”, str1 = “one”, str2 = “”, str3; 字符串长度 • 方法 length( ) • 返回 String的长度 • 与数组不同之处: String不含有 length成员变量 对str3来说,没有创建对象,内容为null.所以无法确定其长度
比较字符串 • 字符类型的数据也是数值类型数据 • 比较字符串大小,实际上就是依次比较其所包含的字符的数值大小 • 小写字母与大小字母是不相同的 • 方法有: • equals() • equalsIgnoreCase() • regionMatches() • compareTo() • compareToIgnoreCase()
equals()方法 • boolean equals(Object anObject) • 比较当前的字符串与指定的对象 • 比较结果为真当且仅当给定的参数不为空,并且具有完全相同的字符序列
String s1=“hello”; String s2=“hello”; String s3=new String(“hello”); s1==s2 s1==s3 s1.equals(s2); s1.equals(s3); “==” 比较地址"equals" 比较内容 方式(1)比方式(2)效率高 应用1:String对象的比较 (1) (2) true false true true
equalsIgnoreCase()方法 • boolean equalsIgnoreCase(String anotherString) • 判别相等,但不区分大小写 • 例如: 在不区分大小写情况下, “hello”与“HELLO”相等
regionMatches()方法 • regionMatches()方法实现子串匹配相等的比较,返回值为boolean类型。若相等则返回true,否则返回false • 格式如下: boolean str1. regionMatches(boolean ignoreCase,int offset,String str2,int offset,int len) • 参数说明: boolean ignoreCase 若为true,则忽略大小写 int offset 确定str1的起始偏移量 String str2 str2为参与比较的另一个串 int offset 确定str2的起始偏移量 int len 确定子串长度
compareTo() 与compareToIgnoreCase() • int compareTo(String anotherString) • 比较两个字符串的内容 • 返回: • 0 : 如果字符串内容完全相同 • 小于0的值: 如果在比较第一个不相同字符,当前字符串的字符的值小于anotherString对应的字符的值 • 大于0的值: 如果在比较第一个不相同字符,当前字符串的字符的值大于anotherString对应的字符的值 • int compareToIgnoreCase(String str) • 比较两个字符串的内容,但不区分大小写
连接字符串 • “+”运算符 • concat()
拷贝字符串 • copyValueOf() • getChars() • toCharArray() • substring()
搜索字符 • charAt(int index) • indexOf(int ch) • indexOf(int ch,int fromIndex) • lastIndexOf(int ch) • lastIndexOf(int ch,int fromIndex)
搜索子串 • indexOf(String str) • indexOf(String str, int fromIndex) • lastIndexOf(String str) • lastIndexOf(String str, int fromIndex) • 返回第一次找到的时下标,如果没有找到,则返回-1
修改字符串 • replace () • toLowerCase() • toUpperCase() • trim ()
String的其他方法 • valueOf()将参数的值转化成相应的字符串 • replace() 替换字符串中的字符或字串 • toUpperCase() • toLowerCase() • toCharArray( )将字符串转换成字符数组 • intern()返回具有相同内容的字符串的引用
4.4 可变字符序列StringBuffer • StringBuffer类创建的串可以修改,可以对串的内容进行增、删、改操作。 • StringBuffer() 构造一个其中不带字符的字符串缓冲区,初始容量为 16 个字符。 • StringBuffer(int capacity)构造一个不带字符,但具有指定初始容量的字符串缓冲区。 • StringBuffer(String str)构造一个字符串缓冲区,并将其内容初始化为指定的字符串内容
StringBuffer方法 • public StringBuffer append(String str) • public StringBuffer insert(int offset,String str) • public StringBuffer delete(int start,int end) • public StringBuffer deleteCharAt(int index) • public StringBuffer replace(int start,int end,String str) • public void setCharAt(int index,char ch) • public StringBuffer reverse( ) • public int length( ) • public int capacity( ) • public void setLength(int newLength)
StringBuffer sb=new StringBuffer(); sb.append(“hello”); sb.append(“ world”); sb sb sb 初始容量为 16 个字符 长度为0 容量为 16 个字符 长度为5 容量为 16 个字符 长度为11 StringBuffer StringBuffer StringBuffer hello hello world StringBuffer对象的内存分配 JVM 堆内存
StringBuffer内部实现是char数组,默认初始化 长度为16,每当字符串长度大于char数组长度时, JVM会构造更大的新数组,并将原先的数组内容 复制到新数组 给StringBuffer设置一个合理的初始化容量值 StringBuffer sb=new StringBuffer(1024); StringBuffer对象的内存分配(续) 新数组长度(新容量)=原容量×2+2
运行期决定连接字符串 String s=“hello”;s=s+“ world”; String s=“hello”; StringBuffer temp=new StringBuffer(); temp.append(s); temp.append(“ world”); S=temp.toString(); 应用:连接字符串操作(1) 编译后的字节码等同于以下源码:
String s=“hello”;s=s+“ world”; 方式(2)比方式(1)效率高 StringBuffer sb=new StringBuffer(); sb.append(“hello”); sb.append(“ world”); 运行期连接字符串操作 (1) (2)