JavaSE 04 数组,javase04数组
JavaSE 04 数组,javase04数组
1、数组
用于保存一组数的容器。
2、数组的优点
⑴ 代码简洁,同时开辟一组空间。
⑵ 数组的空间是连续的。
⑶ 分类存储,查找方便。
3、数组的特点
⑴ 数组的声明时,数据类型可以是基本数据类型,也可以是引用数据类型。
⑵ 数据类型已经声明后,其保存的数据类型必须一致。
⑶ 数据本身属于引用数据类型,所以其遵循引用数据类型的存储和使用的特点。
⑷ 数组名存放在栈中,里面保存了堆中的一组连续空间的首项 [0] 的地址值。数组元素保存在堆中,且是连续的。
4、数组的四要素
数据类型 数组名 数组元素(可以是多个) 下标(0 ~ 数组长度 - 1)
5、访问数组的元素
数组名[下标]
6、数组的声明和使用
⑴ 声明: ① 数据类型[ ] 数组名;
② 数据类型 数组名[ ];
示例: int[ ] arr; // 告诉内存要开辟一串空间,数据类型为int类型,数组名【引用名】为arr。但这是还没有真正开辟空间。
⑵ 开辟空间
数组名 = new 数据类型[数组长度];
示例: arr = new int[5];
⑶ 赋值
数组名[下标] = 值;
示例:arr[0] = 10;
⑷ 使用
数组名[下标];
示例:System.out.println(arr[0]); // 10
注意:① 第⑴、⑵步可以合为一步:
数据类型[ ] 数组名 = new 数据类型[数组长度];
示例: String[ ] strs = new String[10];
②下标必须在数组长度的范围之内,否则会报异常:ArrayIndexOutOfBoundsException
③ 数组声明并开辟长度时,必须指定数组的长度,否则会报错:缺少数组维。
④ 数组如果没有显式地赋值,则系统将为其赋予默认值:
int 0
double 0.0
char ‘\u0000’
boolean false
String null
⑤ 声明并初始化数组元素值,可以合并在一起:
double[ ] scores = new double(){2.4, 4.5, 5.6, 7.8};
或
int[ ] numbers = {2, 23, 34, 48, 23};
但是:
int[ ] num;
num = {2, 234, 34, 72};
这是错误的!(错误: 非法的表达式开始)
7、数组使用的类型
⑴ 静态初始化:
① 步骤1:声明数组并初始化数组元素的值
示例:int[ ] numbers = {2, 3, 45, 76, 21};
② 步骤2:使用
示例:System.out.println(numbers[0]);
⑵ 动态初始化:
① 步骤1:声明数组并开辟长度
示例:String[ ] strs = new String[5];
② 步骤2:给数组元素赋值
示例:strs[0] = “ABC”; strs[1] = “DNF”; strs[3] = “Good”
③ 步骤3:使用
示例:System.out.println(strs[1]);
8、数组的简单使用
⑴ 循环打印
数据类型[ ] 数组名 = new 数组类型[ ]{元素值1, 元素值2, …, 元素值n};
for(int i = 0 ;i < 数组名.length; i++){
System.out.println(数组名[i]);
}
示例:
String[ ] strs = new String[ ]{“ABC”, “DNF”, “GOOD”, “Happy”, “Import”};
for (int i = 0 ; i < strs.length; i++) {
System.out.println(strs[i]);
}
⑵ 求和
注意:数据类型需要为数值型
数据类型[] 数组名 = {元素值1, 元素值2, …, 元素值n};
int sum = 0;
for(int i = 0; i < 数组名.length; i++){
sum += 数组名[i];
}
示例: int[] numbers = {23, 15, 82, 23, 93, 28};
int sum = 0;
for (int i = 0; i < numbers.length; i++) {
sum += numbers[i];
}
System.out.println("和为:" + sum); // 和为:264
⑶ 求最值
注意:数据类型需要为数值型
① 求最大值
示例:
int[] numbers = {223, 135, 820, 213, 193, 128};
int max = numbers[0]; // 注意:这里需要<b>将最大值默认为数组的第一个元素【角标为0】</b>
for (int i = 1; i < numbers.length; i++) { // 因为最大值(max)的声明时,已经将数组的第一个元素的值赋值给了max。所以这里就<b>从角标1开始【即第二个元素】</b>
if (numbers[i] > max) { // 如果遇到了比max大的值,就更新max
max = numbers[i];
}
}
System.out.println("最大值为:" + max); // 最大值为:820
② 求最小值,并附带角标
示例:
int[] nums = {23, 34, 28, 29, 19, 9, 23, 11};
int min = nums[0];
int index = 0; // 这里用index变量来保存角标
for (int i = 1;i < nums.length; i++) {
if (nums[i] < min) {
min = nums[i];
index = i; // 当找到比min小的元素值时,就更新index所保存的角标的值
}
}
System.out.println("最小值为:" + min + ", 其角标为:" + index); // 最小值为:9, 其角标为:5
⑷ 查找
示例:
import java.util.Scanner;
Scanner input = new Scanner(System.in);
String[] usernames = {"Tom", "John", "White", "Danny", "Conan"}; // 定义一个数组名为usernames的数组,里面静态赋值了5个元素值
System.out.print("请输入用户名:");
String name = input.next(); // 用于保存用户输入的用户名
int i = 0; // 这个for循环的循环变量初始值可以放在循环的外面,循环结束后打印输出角标
for (; i < usernames.length; i++) {
if (name.equals(usernames[i])) { // 逐一匹配姓名
System.out.println("欢迎登录 " + name + "!");
break; // 找到了就退出循环
} else if (i == usernames.length - 1) { // 到了usernames数组的最后一项【Conan】,还是没有匹配到
System.out.println("没有找到该用户!");
}
}
if (i < 5) { // i等于5时,就是没有匹配到姓名【当匹配到时,因为if中有break,所以i就不会再执行i++,所以i这时就等于角标值】
System.out.println("角标 : " + i);
}
input.close();
⑸ 排序 【冒泡排序】
思想:先从角标0开始,让角标0和角标1比较,让较大的那个放到后面。然后让角标1和角标2比较,也让较大的那个放到后面。这样依次比较,<b>最终达到从小到大的排序效果</b>。
示例:
int[] nums = {31, 21, 16, 18, 36}; 将这个数组从小到大排序
分析:① 这个nums数组的长度为5,所以需要排序4次。
② 第一次排序需要交换4次;第二次排序需要交换3次;第三次排序需要交换2次;第四次排序需要交换1次。
排序次数 交换次数
1 4
2 3
3 2
4 1
③ 所以需要使用嵌套for循环来实现排序功能。
模版:
for(int i = 1; i < 数组长度; i++){
for(int j = 0; j < 数组长度 - i; j++){
根据相邻两个元素值的“大小”,来交换数组[j]和数组[j + 1]的位置
}
}
用嵌套for循环实现上述示例:
for(int i = 1; i < nums.length; i++){
for(int j = 0; j < nums.length - i; j++){
if(nums[j] > nums[j + 1]){
nums[j] += nums[j + 1];
nums[j + 1] = nums[j] - nums[j + 1];
nums[j] = nums[j] - nums[j + 1];
}
}
}
输出效果:
排序前:
31 21 16 18 36
排序后:
16 18 21 31 36
9、数组的复杂使用
⑴ 数组的赋值
语法: int[ ] arr1 = {23, 34, 12, 10, 8, 32};
int[ ] arr2;
arr2 = arr1; // 数组的赋值
注意:① 基本数据类型赋值时,赋的是一个值(即变量值),而其中一个的改变不会影响到另外一个。
② 引用数据类型赋值时,赋的是一个地址,二者共同引用同一个空间,其中一个的改变会影响到另外一个。
示例: (继续上面的语法代码)
System.out.println("修改数组arr2前的arr1:");
for(int j = 0; j < arr1.length; j++){
System.out.print(arr1[j] + "\t");
}
for(int i = 1; i < arr2.length; i += 2){
arr2[i] = i;
}
System.out.println("\n修改数组arr2后的arr1:");
for(int j = 0; j < arr1.length; j++){
System.out.print(arr1[j] + "\t");
}
System.out.println("\n修改数组arr2后的arr2:");
for(int j = 0; j < arr2.length; j++){
System.out.print(arr2[j] + "\t");
}
输出结果:
修改数组arr2前的arr1:
23 34 12 10 8 32
修改数组arr2后的arr1:
23 1 12 3 8 5
修改数组arr2后的arr2:
23 1 12 3 8 5
因为修改数组arr2后,数组arr1中的元素的值也跟着改变了,所以数组(引用数据类型)的赋值,赋的是地址值。
如果不想出现修改其中一个数组的元素值,另外一个数组的元素值也跟着改变的情况,则需要: 另外开辟一块新的空间,将其中一个数组循环赋值给另外一个数组。
代码:
数据类型[ ] 数组1 = {元素值1, 元素值2, …, 元素值n};
数据类型[ ] 数组2 = new 数据类型[数组1.length];
for(int i = 0; i < 数组1.length; i++){
数组2[i] = 数组1[i];
}
⑵ 数组的反转
① 方法一【借助于中间变量】:
将数组循环,交换开头和结尾的对应位置,直到数组长度的一半为止。
② 方法二【借助新的数组】:
⒈新建一个长度和旧数组长度一样的新数组;⒉将旧数组倒着赋值给新数组;⒊再将新数组的地址值赋值给旧数组。
示例:
int[] nums = {19, 23, 35, 47, 56, 68};
System.out.println("原数组:");
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + "\t");
}
System.out.println("\n方法一【借用中间变量】:"); // 借用中间变量,来交换元素的位置
int temp; // 中间变量,在交换数组元素位置时,用于暂时保存元素值
for (int i = 0, j = nums.length - 1; i < nums.length / 2; i++, j--) { // 只需要交换到数组长度的一半位置即可(奇数长度为:除以2的结果舍掉小数)
temp = nums[i];
nums[i] = nums[j];
nums[j] = temp;
}
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + "\t");
}
System.out.println("\n方法二【借用新数组】:"); // 借用新数组
int[] numsNew = new int[nums.length];
for (int i = nums.length - 1, j = 0; i >= 0; i--, j++) { // 将旧数组倒着赋值给新数组
numsNew[j] = nums[i];
}
nums = numsNew; // 将新数组的地址值赋值给旧数组
for (int i = 0; i < nums.length; i++) {
System.out.print(nums[i] + "\t");
}
输出结果:
原数组:
19 23 35 47 56 68
方法一【借用中间变量】:
68 56 47 35 23 19
方法二【借用新数组】:
19 23 35 47 56 68
⑶ 数组的添加【在数组的尾部添加】
数组的长度一旦固定,就不能再次更改。所以所有数组的添加都要新建数组。
添加步骤:① 创建一个新的数组,长度为旧数组长度 + 1。
② 遍历旧的数组,并赋值到新的数组。数组角标一一对应。
③ 新数组的尾部(length - 1) = 要添加的元素。
④ 将新数组的地址值赋值给旧的数组。
示例: int[] nums = {23, 54, 31, 34};
int[] numsNew = new int[nums.length + 1]; // 新建一个长度比旧数组长度多1的新数组 ①
for(int i = 0; i < nums.length; i++){ // 循环遍历旧数组,并将元素值一一对应地复制给新数组 ②
numsNew[i] = nums[i];
}
int add = 10; // 要插入的数组元素 ③
numsNew[numsNew.length - 1] = add;
nums = numsNew; // 将新数组的地址值赋值给旧数组。 ④
遍历nums的结果为:23 54 31 34 10
⑷ 数组的添加【创建数组时,开辟足够长的长度】
添加步骤:① 新建足够长的数组。
② 定义一个记录当前数组元素总量的int类型的变量。
③ 在添加元素之前,先要判断当前记录元素总量的变量是否已经等于或大于数组的长度。如果大于,则不要添加,否则下角标越界。
④ 添加新元素的方法为:数组名[记录元素总量的变量] = 元素;
⑤ 每添加一个新的元素,就让记录元素总量的变量加1。
示例:
int[] nums = new int[100]; // 假定100够用了
int total = 0; // 记录nums数组的元素总量【当前 为0个】
if(total >= nums.length){ // 判断是否已经无法再添加元素了
return;
}
nums[total] = 10; // 添加元素
total++; // 让total加1
⑸ 数组的插入
插入步骤:① 创建一个新数组,长度比旧数组长度多1。
② 将旧数组的元素值循环赋值给新数组。
③ 新数组: 从要插入的index角标位置的下一位开始,循环将元素向后移动一位。
④ 将要插入数组元素,赋值给新数组[index]。
⑤ 将新数组的地址值赋值给旧数组。
示例: String[] names = {"John", "White", "Tom", "Danny"};
String[] namesNew = new String[names.length + 1]; // ①
for(int i = 0; i < names.length; i++){ // ②
namesNew[i] = names[i];
}
String addName = "Bill"; // 要插入的数组元素
int index = 2; // 要插入的角标位置
for(int j = namesNew.length - 1; j > index; j--){ // ③
namesNew[j] = namesNew[j - 1];
}
namesNew[index] = addName; // ④
names = namesNew; // ⑤
遍历names的结果为:John White Bill Tom Danny
⑹ 数组元素的删除
删除步骤:① 首先找到要删除的数组元素的所在位置(找下标)。
② 从要删除的元素的位置开始,循环前移每个元素的位置。直到倒数第二个数组元素。
③ 将数组的最后一个元素赋为初始值(null、false或0 等)。
示例:
public class Test {
public static void main(String[] args) {
int[] nums = {23, 31, 49, 29, 3, 19};
for (int a = 0; a < nums.length; a++) {
System.out.print(nums[a] + "\t"); // 23 31 49 29 3 19
}
System.out.println();
int num = 49; // 假定要删除49,这个数组元素
int index = 0;
for (int i = 0; i < nums.length; i++) {
if (num == nums[i]) {
index = i;
break;
}
}
for (int j = index; j < nums.length - 1; j++) {
nums[j] = nums[j + 1];
}
nums[nums.length - 1] = 0;
int[] newNums = new int[nums.length - 1];
for (int k = 0; k < newNums.length; k++) {
newNums[k] = nums[k];
}
nums = newNums;
for (int a = 0; a < nums.length; a++) {
System.out.print(nums[a] + "\t"); // 23 31 29 3 19
}
System.out.println();
}
}
10、二维数组
可以称为多个一维数组的组合。
int[ ][ ] nums;
也可以写成:int[ ] nums[ ];【配合着内存图,就可以很清楚地理解二维数组是什么】
Java也支持三维、四维…
int[ ][ ][ ] nums;
int[ ][ ][ ][ ] nums;
特点:
⑴ 同样地,二维数组也具备四要素(数据类型,数组名,数组元素,下标【行下标和列下标,都是从0开始】)。
⑵ 访问二维数组中的某个元素,需要通过
数组名[行下标][列下标] 来访问。
⑶ 数组名.length 来获取二维数组的长度(行数);
数组名[行数].length可以获取某一行的列数。
11、二维数组的声明和使用
⑴ 动态初始化:
① 声明并开辟长度(二维数组的长度)。
⒈ 知道行数和列数:
数据类型[ ][ ] 数组名 = new 数据类型[行数][列数];
2.不知道列数:
数据类型[ ][ ] 数组名 = new 数据类型[行数][ ];
注意:列数可以省略,但是行数不能省略。
② 赋值:
⒈ 固定列数:
for(int i = 0; i < 数组名.length; i++){
for(int j = 0; j < 数组名[i].length; j++){
数组名[i][j] = 元素值;
}
}
⒉ 不固定列数:
for(int i = 0; i < 数组名.length; i++){
数组名[i] = new 数据类型[数组长度];
for(int j = 0; j < 数组名[i].length; j++){
数组名[i][j] = 元素值;
}
}
③ 使用:
for(int i = 0; i < 数组名.length; i++){
for(int j = 0; j < 数组名[i].length; j++){
数组名[i][j]; // 数组元素
}
}
⑵ 静态初始化:
数据类型[ ][ ] 数组名 = new 数据类型{{ … }, { … }, { … }, …};
或
数据类型[ ][ ] 数组名 = {{ … }, { … }, { … }, …};
12、增强for循环
属于一种循环机制,是JDK5.0之后出现的新特性。
它可以遍历集合或数组。
语法: for(元素的数据类型 元素名 : 数组名){
元素名 // 操作每一个元素
}
执行原理:每次从数组或集合中取出对应的元素,直到取不出元素为止。
特点:⑴ 每次只能移动一位。
⑵ 只能向下移动。
⑶ 只能访问,不能修改。
示例:
⑴ 遍历一维数组
int[] numbers = {23, 37, 48, 54, 30};
for(int number : numbers){
System.out.print(number + “\t”);
}
输出结果:23 37 48 54 30
⑵ 遍历二位数组
char[][] chs = {{'a', 'b'}, {'c', 'd', 'e'}, {'f'}};
for (char[] ch : chs) {
for(char c : ch){
System.out.print(c + "\t");
}
System.out.println();
}
输出结果: a b
c d e
f
相关文章
- 暂无相关文章
用户点评