数组
1. 编译环境
JDK1.8 IntelliJ IDEA 2020.1 (Ultimate Edition)
2. 数组的基本概念
2.1 数组的定义
简单的来说,定义了一个数组之后,系统便会为其在内存当中开辟一段连续的内存空间,用于存储多个数据。数组就是一个特殊的变量,普通的int,float,char,double等类型的变量都只能存储一个数据,而数组能存储多个。
2.2 数组的组成
标识 符: 数组的变量名;
元 素:数组当中存储的数据;
数据类型:数组中存储的数据类型,只能是一种;
下 标: 用于访问数组中的指定元素,注意下标是从0开始的。
2.3 数组的使用流程
声明数组 ⇒ 分配空间 ⇒ 存储数据(赋值) ⇒ 使用数组。
3. 数组的基本使用
3.1 语法
法一:
数据类型[] 标识符;
标识符 = new 数据类型[指定数组长度];
法二:
数据类型[] 标识符 = new 数据类型[指定数组长度];
3.2 实际运用
a、代码部分:
// 先声明,后分配空间
int[] nums;
nums = new int[5];
// 声明和分配空间在一行
int[] nums2 = new int[5];
b、两种常用的赋值方法
// 一、通过下标定位数组中空间,然后进行赋值
int[] nums = new int[3];
nums[0] = 1;
nums[1] = 2;
nums[2] = 3;
// 二、通过{}赋值
double[] doubles = new double[]{1.0, 2.0, 3.0};
// 可省略new和数据类型的关键字
double[] doubles1 = {4.0, 5.0, 6.0};
c、测试运行
// 注,使用Arrays.toString方法时,注意导包java.util.Arrays
String str1 = Arrays.toString(nums);
String str2 = Arrays.toString(doubles);
String str3 = Arrays.toString(doubles1);
System.out.println(str1 + "\n" + str2 + "\n" + str3);
个人觉得在使用第二种方法给数组赋值的时候,尽量不要省略new和数据类型的关键字,在不省略的时候,定义数组的整个流程基本上在代码里面都有体现:等号“=”左边表示声明变量,关键字表示为数组分配空间,{}中的内容表示为数组赋值。
3.3 常见问题
a、定义数组常遇到的问题
// 以下两种定义数组的方式时错误的
int[] nums;
nums = {1, 2, 3, 4};
int[] nums1 = new int[4];
nums1 = {1, 2, 3, 4};
// 以下两种方式可以
int[] nums2;
nums2 = new int[]{1, 2, 3};
int[] nums3 = new int[3];
nums3 = new int[]{1, 2, 3, 4};
当你使用定义数组nums3的这种方式时,实际上是执行了两次分配空间的操作,数组的具体大小由第二次的分配空间的语句决定。
int len = nums3.length;
System.out.println("nums3的长度:" + len);
上述用的nums.length是数组的一个属性,通过调用数组的length这个属性可以获取到数组的长度,在String类型的数组中还拥有一个length()方法,注意不要混淆。
深入分析Java中的length和length()
b、常见bug
数组索引超出范围异常。这个异常在数组的使用中经常遇到,一般都是你使用的数组的下标索引超出了你定义的数组的大小,当你忘记数组的下标是从0开始时,经常会遇到这个问题。
4. 数组的应用
4.1 数组排序
a、问题描述:循环录入5位学员成绩,进行升序排列后输出结果。
b、代码实现
// 实例化一个输入流对象,注意导包java.util.Scanner
Scanner input = new Scanner(System.in);
int[] scores = new int[5]; // 声明定义一个长度为5的数组
// 循环输入5位学员的成绩
System.out.println("请输入5位学员的成绩:");
for (int i = 0; i < scores.length; i++) {
scores[i] = input.nextInt();
}
// 调用Arrays.sort方法对数组进行升序排序,注意导包java.util.Arrays
Arrays.sort(scores);
System.out.print("学员成绩按升序排列:");
for (int i = 0; i < scores.length; i++) {
System.out.print(scores[i] + " ");
}
c、运行结果
d、Arrays.sort()方法的一些介绍
有能力的话建议还是看看官方文档 ⇒ java.util.Arrays
4.2 插入算法
a、问题描述:一组有序的字符序列a、b、c、e、f、p、u、z,向次字符序列中插入一个新的字符,要求插入之后字符序列仍保持有序。
b、实现逻辑
- 初始化一个字符数组:注意多分配一个空间给之后要插入的字符,用0占位,表示null;
- 将数组进行升序排序:利用Arrays.sort()方法进行排序,注意,这里字符数组最后的null也是可以进行比较排序的,由于字符之间的大小比较是根据ASCII码表来的,在ASCII码表中,null对应的就是0,比所有字符都要小,所以在排序之后,我们之前预留在数组最后的那一个空间,会跑到首位去;
- 从键盘录入要插入的字符ch;
- 遍历字符数组,将字符ch与数组中的各个元素进行比较,注意是从下标为1的元素开始遍历(第0位为空,是预留位);
- 在没有找到ch插入的位置之前,将数组中的元素向前移一位;
- 在找到ch插入位置之时,将ch赋值给当前元素,获取当前下标,赋值给index;
- 最后打印下标和插入ch后的字符数组。
- 逻辑概念图如下:
(没怎么画过这样的图,见谅。。。)
c、代码实现
Scanner input = new Scanner(System.in);
// 声明定义一个字符数组,最后的0表示占位
char[] letters = new char[]{'a', 'c', 'u', 'b', 'e', 'p', 'f', 'z', 0};
int index = -1;// 初始化目标索引下标
// 将原数组进行升序排列
Arrays.sort(letters);
System.out.print("原字符序列:");
for (int i = 1; i < letters.length; i++) {
System.out.print(letters[i] + " ");
}
System.out.print("\n待插入的字符是:");
char ch = input.next().charAt(0);
// 循环遍历整个数组,将数组中的元素与ch一一进行比较
for (int i = 1; i < letters.length; i++) {
if (letters[i] < ch) { // 当ch大于当前元素时
// 将当前下标数值赋值给前一个下标
letters[i-1] = letters[i];
} else { // 当ch小于或等于当前元素时
// 将ch赋值给当前下标元素
letters[i-1] = ch;
// 获得其下标
index = i-1;
break;
}
}
System.out.println("插入字符的下标是:" + index);
System.out.print("插入后的字符序列是:");
for (int i = 0; i < letters.length; i++) {
System.out.print(letters[i] + " ");
}
d、运行结果
4.3 数组与基本数据类型的一些区别
相较于基本数据类型的变量的使用,数组的使用将为变量开辟内存空间和赋值的操作分开了。这样就导致了在使用的时候,两者之间会有一些差异。当基本数据类型的变量只是声明没有赋值时(例如:int num;),系统并不会为其开辟相应的内存空间;但在数组没有被赋值之前,系统是会为其开辟相应的内存空间并赋予默认值的,如下图所示: