数组
1、创建数组
通过该声明创建的a是被称为数组变量(array variable)的特殊变量
对数组主体中的各个构成元素的访问(读写)是通过将相当于号码的索引(index)赋入[]中进行的:数组变量名[索引]
索引是表示从首个构成元素开始的第几个构成元素的int型整数值,由于首个构成元素的索引是0,因此各个构成元素从开头开始,
可以按照a[O] 、a[l] 、a[2] 、a[3] 、a[4] 的顺序进行访问。
对数组进行赋值和显示:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int[] a = new int[5]; // 数组的声明
a[1] = 37; // 把37赋给a[1]
a[2] = 51; // 把51赋给a[2]
a[4] = a[1] * 2; // 把74赋给a[4]
// 显示全部元素的值
System.out.println("a[" + 0 + "] = " + a[0]);
System.out.println("a[" + 1 + "] = " + a[1]);
System.out.println("a[" + 2 + "] = " + a[2]);
System.out.println("a[" + 3 + "] = " + a[3]);
System.out.println("a[" + 4 + "] = " + a[4]);
}
}
输出:未赋值的a[0]和a[3]的值都是0,数组的构成元素会自动初始化为0
各类型默认值:
2、获取数组中的元素个数
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int[] a = new int[5]; // 数组的声明
for (int i = 0; i < a.length; i++)
a[i] = i + 1;
for (int i = 0; i < a.length; i++)
System.out.println("a[" + i + "] = " + a[i]);
}
}
输出:
如上述代码中的 a.length---数组变量名.length:该表达式用来获取数组的元素个数
表示数组元素个数的length不是int型,而是final int型;因此不可以给length赋值,不可以如a.length=10这样随意改变数组的元素个数(编译时会发生错误)
3、读入数组元素的值
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("元素个数:");
//将数值元素个数读入到变量n中
int n = stdIn.nextInt(); // 读入元素个数
int[] a = new int[n]; // 创建数组
for (int i = 0; i < n; i++) {
System.out.print("a[" + i + "] = ");
a[i] = stdIn.nextInt();
}
for (int i = 0; i < n; i++)
System.out.println("a[" + i + "] = " + a[i]);
}
}
输出:
将随机数赋给数组中的全部元素,并显示为横向柱形图
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);
System.out.print("元素个数:");
int n = stdIn.nextInt(); // 读入元素个数
int[] a = new int[n]; // 创建数组
for (int i = 0; i < n; i++)
a[i] = 1 + rand.nextInt(10); // 1~10的随机数
for (int i = 0; i < n; i++) {
System.out.print("a[" + i + "] : ");
for (int j = 0; j < a[i]; j++)
System.out.print('*');
System.out.println();
}
}
}
输出:
4、数组的初始化和赋值
将数组中的各个元素初始化为1, 2, 3, 4, 5,并进行显示
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
for (int i = 0; i < a.length; i++)
System.out.println("a[" + i + "] = " + a[i]);
}
}
输出:
数组的初始值就是那些在大括号中的、用逗号分隔并逐一赋给各个元素的值;
创建的数组中的元素个数会根据初始值的个数自动进行设定;
上面程序中(尽管没有显式使用new)会创建一个元素个数为5的数组,从头开始依次将各个元 素初始化为1、2、3、4、5。
读入分数并显示总分和平均分:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
int sum = 0; // 总分
final int ninzu = 5; // 人数
int[] tensu = new int[ninzu]; // 分数
System.out.println("请输入" + ninzu + "名学生的分数。");
for (int i = 0; i < ninzu; i++) {
System.out.print((i + 1) + "号的分数:");
tensu[i] = stdIn.nextInt(); // 读入tensu[i]
sum += tensu[i]; // 将tensu[i]加到sum上
}
System.out.println("总分为" + sum + "分。");
System.out.println("平均分为" + (double)sum / ninzu + "分。");
}
}
输出:
5、计算数组元素中的最大值
如果数组的元素个数为3, 那么三个元素a[O]、a[l]、a(2]中最大值的计算方法如下:
max= a[0];
if (a[l] > max) max= a[l];
if (a[2] > max) max= a[2];
元素个数为n, 计算数组a中最大值的程序如下所示:
max = a[O];
for (int i = l; i< a.length; i++)
if (a[i] > max) max = a[i];
计算元素个数为5的数组中元素最大值的过程::
逐个依次访问数组元素的操作称为遍历,在遍历过程中,当if语句成立(查看的元素值大于当时的最大值max)时,
则将a[i]的值赋给max 当遍历结束时,数组a中的最大元素值就保存到了max中
读入分数并显示最高分:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
final int ninzu = 5; // 人数
int[] tensu = new int[ninzu]; // 分数
System.out.println("请输入" + ninzu + "名学生的分数。");
for (int i = 0; i < ninzu; i++) {
System.out.print((i + 1) + "号的分数:");
tensu[i] = stdIn.nextInt(); // 读入tensu[i]
}
int max = tensu[0];
for (int i = 1; i < tensu.length; i++)
if (tensu[i] > max) max = tensu[i];
System.out.println("最高分为" + max + "分。");
}
}
输出:
线性查找:
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);
final int n = 12; // 元素个数
int[] a = new int[n]; // 声明数组
for (int j = 0; j < n; j++)
a[j] = rand.nextInt(10);
System.out.print("数组a中全部元素的值\n{ ");
for (int j = 0; j < n; j++)
System.out.print(a[j] + " ");
System.out.println(" }");
System.out.print("要查找的数值:");
int key = stdIn.nextInt();
int i;
for (i = 0; i < n; i++)
if (a[i] == key)
break;
if (i < n) // 查找成功
System.out.println("该元素是a[" + i + "]。");
else // 查找失败
System.out.println("该元素不存在。");
}
}
输出:在线性查找算法中,当存在多个与键值相同的元素时,找到的是它们当中最开头的元素
6、扩展for语句
计算并显示数组中全部元素的总和
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
double[] a = { 1.0, 2.0, 3.0, 4.0, 5.0 };
for (int i = 0; i < a.length; i++)
System.out.println("a[" + i + "] = " + a[i]);
double sum = 0; // 总和
for (double i : a) //:相当于‘...中的’
sum += i;
System.out.println("全部元素的总和为" + sum + "。");
}
}
输出:
上述for循环:遍历数组a从开头到末尾的每一个元素,在循环体中当前正在查看的元素用 i 来表示;
变量 i 并不是表示"索引"的int型整数数值,而是表示double型的"遍历过程中正在查看的元素”。
使用扩展for循环的好处:
• 省去了确认数组长度(元素个数)的操作
• 可以使用与迭代器相同的方法来执行遍历
7、对数组进行倒序排列
交换首个元素a [0]与末尾元素a [6]的值;然后循环执行各自内侧的一个元素值的交换
如果元素个数为n, 则交换次数为n/2 这里的余数会舍弃掉;这是因为当元素个数为奇数时,中间的元素无需进行交换
对数组中的元素进行倒序排列并显示
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);
System.out.print("元素个数:");
int n = stdIn.nextInt(); // 读入元素个数
int[] a = new int[n]; // 声明数组
for (int i = 0; i < n; i++) {
a[i] = 10 + rand.nextInt(90);
System.out.println("a[" + i + "] = " + a[i]);
}
for (int i = 0; i < n / 2; i++) {
int t = a[i];
a[i] = a[n - i - 1];
a[n - i - 1] = t;
}
System.out.println("元素的倒序排列执行完毕。");
for (int i = 0; i < n; i++)
System.out.println("a[" + i + "] = " + a[i]);
}
}
输出:
8、数组的复制
数组的赋值(错误)
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
int[] a = {1, 2, 3, 4, 5};
int[] b = {6, 5, 4, 3, 2, 1, 0};
System.out.print("a = "); // 显示数组a中的全部元素
for (int i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
System.out.println();
System.out.print("b = "); // 显示数组b中的全部元素
for (int i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();
b = a; // 将数组a复制到b(?)
a[0] = 10; // 改写数组a[0]的值
System.out.println("将a赋给了b。 ");
System.out.print("a = "); // 显示数组a中的全部元素
for (int i = 0; i < a.length; i++)
System.out.print(a[i] + " ");
System.out.println();
System.out.print("b = "); // 显示数组b中的全部元素
for (int i = 0; i < b.length; i++)
System.out.print(b[i] + " ");
System.out.println();
}
}
输出:
a是元素个数为5的数组{1,2,3,4,5},b是元素个数为7的数组{6, 5, 4, 3, 2, 1, 0};
执行b=a的赋值操作,接下来将10写入到a[0]中。因此,结果应该是数组a变成{10,2,3,4,5},数组b 变成{1,2,3,4,5}
但从运行结果可以看出,a和b都变成了{10,2,3,4,5},
该运行结果表明了如下内容:
赋值后的数组a和b 变成了同一个数组即赋值后的数组变量a 和b 引用了同—个数组主体
使用赋值运符符=进行数组变量的赋值,并不会复制全部元素,赋值运算符的动作如图:
赋值操作b=a是将a的引用目标赋给b 由千是引用目标的复制, 因此赋值的最终结果就变成了数组变量b引用数组a的主体
复制数组时,需要使用循环语句逐一复制全部元素 :
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner stdIn = new Scanner(System.in);
System.out.print("元素个数:");
int n = stdIn.nextInt(); // 读入元素个数
int[] a = new int[n];
int[] b = new int[n];
for (int i = 0; i < n; i++) { // 数组a中读入数值
System.out.print("a[" + i + "] = ");
a[i] = stdIn.nextInt();
}
for (int i = 0; i < n; i++) // 将数组a中的全部元素复制到b中
b[i] = a[i];
System.out.println("已经将a中的全部元素复制到了b中。 ");
for (int i = 0; i < n; i++) // 显示数组b
System.out.println("b[" + i + "] = " + b[i]);
}
}
输出:
8、字符串数组
字符串可以用String型来表示,因此字符串数组的类型就是String[]型。
import java.util.Random;
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Random rand = new Random();
Scanner stdIn = new Scanner(System.in);
String[] monthString = {
"January", "February", "March", "April", "May", "June", "July",
"August", "September", "October", "November", "December"
};
int month = rand.nextInt(12); // 目标月份:0~11的随机数
System.out.println("题目是" + monthString[month]);
while (true) {
System.out.print("是几月呢:");
int m = stdIn.nextInt();
if (m == month + 1) break;
System.out.println("回答错误。");
}
System.out.println("回答正确。");
}
}
输出:
9、引用类型和对象
显示数组变量的值
public class Main {
public static void main(String[] args) {
int[] a = new int[5];
System.out.println("a = " + a);
a = null;
System.out.println("a = " + a);
}
}
输出:程序显示的并不是数组元素的值. 而是数组变量本身的值
int[] a = new int[5]:数组的声明--使用new创建的数组主体与一般的变量不同,它是在程序运行时创建的,因此会被动态分配存储空间,数组主体与一般变量的性质不同,被称为对象(object)。用于指向对象的变量的类型就是引用类型(reference type)。数组变量的类型是数组类型(array type), 这是引用类型的一种
a = null,null赋给数组变址a,null是被称为空常量(null literal)的一种常址 。
被赋入空常址的a就是空引用(null reference)。 空引用是表示什么都不引用的一种特殊引用.其类型就是空类型(null type)。
垃圾回收
对于数组变量,当赋入null, 或者赋入其他数组主体的引用时,数组主体将不再被任何变量引用,变为垃圾。
垃圾残留会导致存储空间不足, 因此,不再被任何变量引用的对象所占用的空间会被自动释放,以便能够再次使用。
像这样,释放不再需要的对象空间,以便能够再次使用的处理称为垃圾回收(garbage collection)。
10、final 数组
数组变量还可以像下面这样声明为final变量:
final int[] a = new int[5];
变成final (值不可以被改写)的是数组a的引用目标, 而各个元素的值可以被改写
a[0] = 10; //正确
a= null; //错误
a = new int[l0]; //错误
如果将数组变量声明为final,就可以防止误赋入null, 或者赋入其他数组主体的引用