第五章 数组和字符串
5.1 熟悉数组声明与使用方法
在Java中,数组是具有相同数据类型的有序数据的集合,它是一个对象。其中,这些数据使用同一标识符作为数组名;数组中的每个数据称为数组元素,可通过下标来访问。数组分为一维数组和多维数组。
一、一维数组
1.一维数组的声明
声明一个数组仅为数组指定了数组名和元素的数据类型,并未指定数组元素的个数和初始值,此时系统不会为数组分配内存空间。
一维数组的声明格式如下:
数据类型[] 数组名;
数据类型 数组名[];
数据类型可以是简单数据类型或复合数据类型。
[]表示声明的是数组,其个数表示数组的维数。它可以放在数据类型右侧(此为最常用的方法)或数组名称右侧。
2.一维数组的初始化
数组声明后需要初始化才可以使用,通过初始化可以为数组分配内存空间,或者为数组元素赋值。数组的初始化分为静态初始化和动态初始化。
(1)静态初始化
静态初始化是指声明数组的同时为数组元素赋值,其语法格式如下:
数据类型[] 数组名= {元素1初值,元素2初值,元素3初值…};
例如:
double score[] = {78.0, 89.5, 66.0, 93.0 };
(2)动态初始化
动态初始化是指利用new运算符为数组分配内存空间。其语法格式如下:
数据类型[] 数组名; 数组名= new 数据类型[数组长度];
例如:int[] salary; salary = new int[4];
提示:数组的声明和初始化也可以放在一条语句中完成,例如:int[] salary=new int[4]。
3.一维数组的使用
当数组创建并初始化后,就可以使用数组中的各个元素了。其语法格式如下:
数组名[数组下标];
数组下标用来唯一标识数组中的每一个元素,它可以是整数或表达式。在Java中,所有数组下标都是从0开始到“数组长度-1”结束,如name[0],name[1]等。
数组对象有length属性表示数组的长度。
int[] salary= new int[3];
salary [0] = 1000; //为第1个元素赋值
salary [1] = 1800;
salary [2] = 1500;
int len = salary.length; //取得数组的长度
for(int i=0;i<len;i++){
System.out.println(salary[i]); //输出数组中的元素
}
实例5-1 冒泡排序
【实例描述】
采用冒泡排序算法将10个整数按照从小到大的顺序排列。
【技术要点】
冒泡排序是一种简单的交换排序。其基本思路是,从数列左边开始扫描待排序的元素,在扫描过程中依次对相邻元素进行比较,将较大值元素后移。每经过一轮排序后,值最大的元素将移到末尾,此时记下该元素的位置,下一轮排序只需比较到此位置即可。如此重复,直到比较最后两个元素。
对n个元素冒泡排序时,总共需要进行n-1轮。第1轮需要比较n-1次,第2轮需要比较n-2次,第i轮需要比较n-i次,最后一轮需要比较1次。
// NumberSort.java
package Chapter5;
public class NumberSort {
public static void main(String[] args) {
int[] array = { 3, 1, 6, 2, 9, 0, 7, 4, 5, 8 };
System.out.print("数组排列前的顺序为:");
for (int i = 0; i < array.length; i++) { // 输出数组中的每个元素
System.out.print(array[i] + " ");
}
int temp; // 存储交换的变量值
for (int i = 0; i < array.length - 1; i++) { // 比较n-1轮
for (int j = 0; j < array.length - i - 1; j++) { // 每轮比较
if (array[j] > array[j + 1]) {
temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
System.out.println();
System.out.print("数组排列后的顺序为:");
for (int i = 0; i < array.length; i++) { // 输出数组中的每个元素
System.out.print(array[i] + " ");
}
}
}
二、多维数组
多维数组被看成是数组的数组,即高维数组中的元素又是一个低维数组。
1.二维数组的声明
二维数组的声明格式如下:
数据类型[][] 数组名;数据类型 数组名[][];
例如:int[][] a; int a[][];
2.二维数组的初始化
(1)静态初始化
静态初始化是指在声明数组的同时给元素赋初值。例如:
int a[][] ={{34,25},{100,43},{1000,453,39}};
(2)动态初始化
动态初始化是指用new关键字为数组分配内存空间,并指定数组元素的行数和列数,但不给数组元素赋初值。
① 直接方式:
在数组初始化时直接指定二维数组的行数和列数,
例如:
int a[][] = new int [3][2];
② 逐级方式:
逐级方式是指首先为二维数组分配行数,再为每一行分配列数。
例如:
int a[][] = new int [2][];
a[0]= new int[1]; a[1]= new int[2];
3.二维数组的使用
二维数组的使用和一维数组相似,其语法格式如下:
数组名[index1][index2];
例如:
int a[][] = new int [2][];
a[0]= new int[1];
a[1]= new int[2];
a[0][0]=5;
a[1][0]=20;
a[1][1]=13;
实例5-2 选择题评分
【实例描述】
编写程序,给选择题进行评分。假设有5个学生和10个问题,学生对问题给出的答案存储在二维数组中,每行记录一名学生对所有问题的答案。统计正确答案的个数并将其显示出来。
【技术要点】
学生的答案存储在一个二维数组中,如下所示。
// GradeExam.java
package Chapter5;
public class GradeExam {
public static void main(String[] args) {
char[][] answers = { // 定义存储学生答案的数组
{ 'A', 'B', 'A', 'C', 'C', 'D', 'E', 'E', 'A', 'D' },
{ 'D', 'B', 'A', 'B', 'C', 'A', 'E', 'E', 'A', 'D' },
{ 'E', 'D', 'D', 'A', 'C', 'B', 'E', 'E', 'A', 'E' },
{ 'C', 'B', 'A', 'E', 'D', 'C', 'E', 'E', 'A', 'D' },
{ 'A', 'B', 'D', 'C', 'C', 'D', 'E', 'E', 'A', 'D' } };
char[] keys = { 'D', 'B', 'D', 'C', 'C', 'D', 'A', 'E', 'A', 'D' };// 定义正确答案的数组
for (int i = 0; i < answers.length; i++) {
int correctCount = 0; // 记录答对的题目个数
for (int j = 0; j < answers[i].length; j++) {
if (answers[i][j] == keys[j]) // 判断给出的答案是否正确
correctCount++; // 改变答对的题目个数
}
System.out.println("学生" + i + "'答对题目的个数为:" + correctCount);
}
}
}
三、对象数组
在数组定义中,数组元素可以定义为基本数据类型,也可以定义为类对象等引用类型。数组元素的类型为类对象的数组称为对象数组。
// Exam_1.java
package Chapter5;
class Student { // 声明Student类
String name; // 声明成员变量
int age;
public Student(String name, int age) { // 构造方法
this.name = name;
this.age = age;
}
}
public class Exam_1 {
public static void main(String args[]) {
Student[] stu = new Student[3]; // 声明对象数组
stu[0] = new Student("lily", 20); // 为对象数组元素初始化
stu[1] = new Student("lucy", 18);
stu[2] = new Student("john", 21);
for (int i = 0; i < stu.length; i++) { // 输出对象的信息
System.out.println(stu[i].name + " " + stu[i].age);
}
}
}
程序的运行结果:
lily 20
lucy 18
john 21
四、数组作为方法的参数
在Java中,数组可以作为方法的参数传递。数组作为方法的实参时传递的是引用,从而会使实参和形参拥有相同的内存空间。若在方法中更改了形参的值,实参的值也将被改变。
// Exam_2.java
package Chapter5;
public class Exam_2 {
public static void main(String args[]) {
double a[] = { 1.1, 3.4, -9.8, 10 }; // 定义数组并初始化
// 定义存储最大值、最小值和平均值的数组,将数组a作为方法的实参
double b[] = max_min_ave(a);
for (int i = 0; i < b.length; i++)
// 输出最大值、最小值与平均值
System.out.println("b[" + i + "]=" + b[i]);
}
// 取得数组的最大值、最小值和平均值的方法,返回值为数组类型
static double[] max_min_ave(double a[]) {
double res[] = new double[3];
double max = a[0], min = a[0], sum = a[0];
for (int i = 0; i < a.length; i++) {
if (max < a[i])
max = a[i]; // 取得数组中的最大值
if (min > a[i])
min = a[i]; // 取得数组中的最小值
sum += a[i]; // 取得数组中元素的总和
}
res[0] = max;
res[1] = min;
res[2] = sum / a.length; // 得到数组元素的平均值
return res; // 返回数组引用
}
}
5.2 了解字符串的创建于使用方法
一、String类
1.声明字符串
String s;
2.创建字符串
(1)创建字符串对象时直接赋值。例如:
String s1="hello";
(2)由一个字符串创建另一个字符串。例如:
String s1 = "hello"; String s2 = new String(s1);
(3)由字符型数组来创建字符串。例如:
char[] c = {'a','b','c'}; String s = new String(c);
二、获取字符串的长度
使用方法length()可以获取一个字符串的长度。
例如:String s = “hello world!”; int len = s.1ength(); //len的值为12
三、字符串的连接
Java中除了可使用“+”运算符进行字符串的连接外,还提供了concat()方法进行两个字符串的连接。
例如:
String s1 ="hello"; String s2="world";
String s3 = s1.concat(s2); //s3的值为“helloworld”
四、字符串的比较
1.equals方法
字符串对象调用String类的public boolean eaquals(String s)方法,可比较当前字符串对象的内容是否与参数指定的字符串s的内容相同。
例如:
String s1=new String("hello");
String s2=new String("hello");
s1.equals(s2); //true,s1、s2的内容都为hello
2.equalsIgnoreCase方法
字符串对象调用public boolean equalsIgnoreCase(String s)方法,也可比较当前字符串对象与参数指定的字符串s是否相同,并且比较时忽略大小写。
例如:
String s1=new String("hello");
String s2=new String("Hello");
s1.equalsIgnoreCase(s2); //true
3.compareTo方法
字符串对象使用public int compareTo(String s)方法,可按照字典顺序与参数s指定的字符串比较大小。如果当前字符串与s相同,该方法返回值0;如果当前字符串对象大于s,该方法返回正值;如果小于s,该方法返回负值。
例如:
String s=new String("abcde");
s.compareTo("boy"); //小于0
s.compareTo("aba"); //大于0
s.compareTo("abcde"); //等于0
五、字符串的检索
1.搜索指定串出现的位置
public int indexOf(String s):字符串调用该方法从当前字符串的头
开始检索字符串s,并返回首次出现s的位置。如果没有检索到字
符串s,该方法返回值为-1。
public int lastIndexOf(String s):字符串调用该方法从当前字符串
的头开始检索字符串s,并返回最后出现s的位置。如果没有检索
到字符串s,该方法返回值为-1。
例如:
String s=new String("I am a good cat");
s.indexOf("a"); //值是2
s.lastIndexOf("a"); //值是13
2.搜索指定字符出现的位置
public int indexOf(int char):字符串调用该方法从当前字符串
的头开始检索字符char,并返回首次出现char的位置。如果
没有检索到字符char,该方法返回值是-1。
public int lastIndexOf(int char):字符串调用该方法从当前字
符串的头开始检索字符char,并返回最后出现char的位置。
如果没有检索到字符char,该方法返回值是-1。
例如:
String s=new String("I am a good cat");
s.indexOf('a'); //值是2
s.lastIndexOf('a'); //值是13
六、String类的其他常用方法
1.字符串的截取
public String substring(int startpoint):字符串对象调用该方法
获得一个当前字符串的子串,该子串是从当前字符串的
startpoint处截取到最后所得到的字符串。
public String substring(int start,int end):字符串对象调用该方
法获得一个当前字符串的子串,该子串是从当前字符串的
start处截取到end处所得到的字符串,但不包括end处所对应
的字符。
例如:
String china="I love China";
String s=china.substring(2,5); //s是lov
String s1=china.substring(2); //s1是love China
2.字符串转换为大小写
public String toLowerCase():字符串对象调用该方法使得当前|
字符串的全部字符转换为小写。
public String toUpperCase():字符串对象调用该方法使得当前
字符串的全部字符转换为大写。例如:
String s=new String("Hello");
s.toLowerCase(); //值是hello
s.toUpperCase(); //值是HELLO
3.字符串的替换
public String replace(char old,char new):字符串对象s调用该方法可以
获得一个字符串对象,这个对象是用参数new指定的字符替换s中由
old指定的所有字符而得到的字符串。
public String replaceAll(String old,String new):字符串对象s调用该方
法可以获得一个字符串对象,这个字符串对象是通过用参数new指定
的字符串替换s中由old指定的所有字符串而得到的字符串。
publicString trim():一个字符串s通过调用该方法得到一个字符串对
象,该字符串对象是s去掉前后空格后的字符串。
七、字符串转化为相应的数值
1.字符串转换为数值
通过调用java.lang包中Integer类的类方法public static int parseInt(String s),可以将数字格式的字符串,如“1234”,转化为int型数据。
例如:
String s="1234";int x=Integer.parseInt(s); //x值是1234
类似地,可使用java.lang包中Byte、Short、Long、Double类的类方法,将数字格式的字符串转化为相应的基本数据类型。
2.数值转换为字符串
使用String类的valueOf方法可将byte、int、long、float、double等类型的数值转换为字符串。
例如:
String s=String.valueOf(7894.4467);
float x=345.6675f;
String s1=String.valueOf(x);
八、字符串与字符数组和字节数组之间的转换
借助字符串类String的构造方法和成员方法,我们可以方便地将字节数组和字符数组转换为字符串,或者将字符串转换为字节数组或字符数组。
// 声明字节数组和字符数组
byte[] b = { 65, 66, 67, 68, 69, 70, 71, 72, 73, 74, 75 };
char[] c = { 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', 'j', 'k' };
// 声明字符串对象
String str;
// 将字节数组转换为字符串
str = new String(b);
// 将字节数组中指定位置(5)开始的指定长度(20)的字节转换为字符串
str = new String(b, 2, 8);
// 将字符数组转换为字符串
str = new String(c);
// 将字符数组中指定位置(5)开始的指定长度(20)的字符转换为字符串
str = new String(c, 2, 8);
// 将字符串转换为字节数组
b = str.getBytes();
// 将字符串转换为字符数组
c = str.toCharArray();
实例5-3 检测回文串
【实例描述】
利用String类的常用方法检测字符串是否为回文串。
【技术要点】
对于一个字符串,如果从前向后和从后向前读都一样,则称为回文串。例如:单词mom、dad和noon等都是回文串。
判断是否为回文串的方法是:先判断该字符串的第一个字符和最后一个字符是否相等,如果相等,检查第二个字符和倒数第二个字符是否相等。这个过程一直进行,直到出现不匹配的情况或者串中所有的字符都检查完毕。
// CheckString.java
package Chapter5;
import java.util.Scanner;
public class CheckString {
public static void main(String[] args) {
String checkStr = null;
System.out.println("请输入要检测的字符串:");
Scanner in = new Scanner(System.in);
checkStr = in.nextLine(); // 存储用户输入的字符串
if (isPaildrome(checkStr)) { // 判断输入的字符串是否为回文串
System.out.println(checkStr + "是回文串。");
} else {
System.out.println(checkStr + "不是回文串。");
}
}
private static boolean isPaildrome(String check) {
int low = 0; // 定义首字符的索引
int high = check.length() - 1; // 定义尾子符的索引
while (low < high) {
// 检测首尾两个字符是否相等
if (check.charAt(low) != check.charAt(high))
return false;
low++;
high--;
}
return true;
}
}
九、StringBuffer类
1.StringBuffer类字符串的定义
在Java中,String类的对象一旦被初始化,它的值和所分配的内存就不能被改变了。如果想要改变它的值,则必须创建一个新的String对象。因此,String类的对象会消耗大量的内存空间。
例如:
String sample1 = new String("Hello");
sample1 += "my name is";
sample1 += "xiaohong";
这种方法的问题在于一个简单的字符串拼接消耗了太多的内存资源。为了解决这种问题,Java中提供了StringBuffer类。
2.用StringBuffer类处理字符串
StringBuffer类的构造方法有以下几种:
StringBuffer():构造一个不带字符的字符串对象,其初始容量是16个字符。
StringBuffer(int capacity):构造一个不带字符但具有指定初始容量
capacity的字符串对象。
StringBuffer(String s):构造一个字符串对象,并将其内容初始
化为指定字符串s。
例如:
StringBuffer sb1=new StringBuffer(); //创建一个空的字符串
StringBuffer sb2=new StringBuffer(30); //创建容量大小为30的 空字符串
StringBuffer sb3=new StringBuffer("Hello");//创建初始值为Hello的字符串
StringBuffer类的主要操作方法是append()和insert()方法,它们能将给定字符追加或插入到当前字符串内容中。append()方法将给定的字符追加到当前字符串的末尾;而insert()方法则在当前字符串的指定位置插入字符。
class Exam_3{
public static void main(String args[]){
StringBuffer s1=new StringBuffer();
StringBuffer s2=new StringBuffer(5);
StringBuffer s3=new StringBuffer("hello");
s1.append("hello");
s2.insert(0,"hello");
}
提示:append()和insert()方法有十余种重载形式,它们允许将各 种数据类型的数值追加到当前对象的末尾或插入到当前对象中。
无论是append()方法,还是insert()方法,它们都是在原有对象基础上进行操作的,并没有创建新的对象。
本章小结
本章首先重点介绍了一维数组的创建和使用方法,并且通过二维数组的学习,熟悉了多维数组的创建和使用方法。最后介绍了String类及StringBuffer类及其常用的方法。