目录
一、数组定义
数组是引用数据类型,存储的是数组在内存中的地址信息。
1、静态初始化数组
定义数组时直接给数组赋值
2、数组的动态初始化
只确定元素的类型和数组长度。
两种数组定义时的特点和场景:
- 当前已经知道存入的元素值,用静态初始化。
- 当前还不清楚要存入哪些数据,用动态初始化。
3、数组元素的访问
通过元素索引获取对应值。
4、数组的几个注意事项:
- “数据类型[ ] 数组名” 也可以写成 “数据类型 数组名[ ]”。
double[] score1 = {12,3.0,35.6}; //建议使用这种
//等价于
double score2[] = {1,23};
- 什么类型的数组存放什么类型的数据,否则报错。
- 数组一旦定义出来,程序执行的过程中,长度、类型就固定了
二、数组的遍历
将数组元素一个一个遍历输出。
//学会数组元素的遍历
int[] data = {1,2,3,4,5,6,7,8,9};
for (int i = 0; i < data.length; i++) {
System.out.println(data[i]);
}
快速生成数组遍历: 数组名.fori + 回车
三、数组的案例
案例1、:输入班级学生姓名并进行随机点名
import java.util.Random;
import java.util.Scanner;
public class RandomTest {
public static void main(String[] args) {
//创建扫描器对象
Scanner sc = new Scanner(System.in);
//创建随机数对象
Random r = new Random();
//定义一个引用型数组存放学生姓名
String[] stuName = new String[5];
//通过循环输入学生姓名
for (int i = 1; i < 5; i++) {
//依次获取键盘输入的姓名给数组
System.out.print("第" + i + "个学生为");
stuName[i] = sc.next();
}
//生成随机数进行随机点名
int num = r.nextInt(5) + 1;
System.out.println("回答问题的人是:");
System.out.println(stuName[num]);
}
}
案例2、求公司五个人的总销售额
public class ArrayListTest1 {
public static void main(String[] args) {
int[] sale = {16,26,36,6,100};
System.out.print("五名员工的销售额分别为:");
for (int i = 0; i < sale.length; i++) {
System.out.print(sale[i] + "\t");
}
int sum = 0;
for (int i = 0; i < sale.length; i++) {
sum += sale[i];
}
System.out.println();
System.out.print("他们的和为:");
System.out.println(sum);
}
}
待解决的问题:如何将遍历的数组元素不换行且元素之间空格隔开
案例3、求数组最大值
public class ArrayListTest2 {
public static void main(String[] args) {
//数组求最大值 打擂台算法
int[] arr = {15,10,5,98,60,41};
//让第一个人当擂主
int max = arr[0];
//定义一个擂台
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
System.out.print("数组中的最大值是:" + max);
}
}
案例4、猜数并 遍历数组
随机生成五个数,猜数字,如果猜到五个中的一个则猜中并输出第一次出现的位置,打印五个数字,否则猜数错误,继续猜。
import java.util.Random;
import java.util.Scanner;
public class ArrayListTest3 {
public static void main(String[] args) {
//创建动态初始化数组
int[] num = new int[5];
//创建随机数对象
Random r = new Random() ;
//创建扫描器对象
Scanner sc = new Scanner(System.in);
//随机生成5个数送给num容器
for (int i = 0; i < num.length; i++) {
//接收随机数
num[i] = r.nextInt(20) + 1;
}
OUT:
//开始猜数字
while (true) {
System.out.print("您猜的数字是:");
int userNum = sc.nextInt();
for (int i = 0; i < num.length; i++) {
if (userNum == num[i]) {
System.out.println("恭喜成功猜中,第一次出现的位置为" + i);
//强制跳出死循环
break OUT;
}
}
System.out.println("未猜中请继续");
}
for (int i = 0; i < num.length; i++) {
System.out.print(num[i] + "\t");
}
}
}
案例5、随机排名
将接收到的随机索引与当前遍历的元素位置互换产生新的数组
import java.util.Random;
import java.util.Scanner;
public class ArrayListTest {
public static void main(String[] args) {
//创建扫描器对象
Scanner sc = new Scanner(System.in);
//创建随机数对象
Random r = new Random();
//动态初始化数组,存放员工数据
int[] num = new int[5];
//依次录入五名员工工号
System.out.println("请依次录入五个员工的工号:");
for (int i = 0; i < num.length; i++) {
num[i] = sc.nextInt();
}
System.out.println("随机排名后的顺序为:");
for (int i = 0; i < 5; i++) {
//接收随机对象
int index = r.nextInt(num.length);
//将接收到的随机索引与当前遍历的元素位置互换产生新的数组
//实现两杯饮料A,B互换
//拿来第三个空杯子C并将一杯水B倒进空杯子中
int temp = num[i];
//再将A中的水倒入B杯中
num[i] = num[index];
//最后将C杯中的水倒入A杯中
num[index] = temp;
}
//遍历新数组
for (int i = 0; i < num.length; i++) {
System.out.print(num[i] + "\t1");
}
}
}
四、数组排序
1、冒泡排序
注意外层循环表示循环轮数,内部循环表示比较的次数,每轮结束都会产生一个最大值不需要继续再比较。
import java.util.Scanner;
public class BubbleSort {
public static void main(String[] args) {
//冒泡排序
//新建扫描器对象
Scanner sc = new Scanner(System.in);
//动态初始化数组
int[] arr = new int[5];
System.out.println("请输入五个数");
for (int i = 0; i < arr.length; i++) {
//依次输入数组元素
arr[i] = sc.nextInt();
}
//五个数: 1 2 3 4 5
//对应索引 0 1 2 3 4
//进行数组排序
//外层循环表示循环的轮数,i=0表示从第一轮开始,总共进行5-1=4次
for (int i = 0; i < arr.length-1; i++) {
//内层循环表示循环的次数,j=0表示从arr[0]开始比较,总共比较arr.length-i-1次
//总共比较arr.length-i-1次原因:每轮比较结束后都会有一个最大值排出来进行占位,就不需要在继续比较
//而i是从0开始,所以每次内循环都少减了1,因此加上减1
for (int j = 0; j < arr.length - i -1; j++) {
if (arr[j] > arr[j+1]) {
int temp = arr[j];
arr[j] = arr[j+1];
arr[j+1] = temp;
}
}
}
System.out.println("排序后的数组为:");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + "\t");
}
}
}
2、选择排序
public static void main(String[] args) {
int[] arr = {5,1,3,2};
//定义外部循环,控制循环轮数
for (int i = 0; i < arr.length; i++) {
// 5 1 3 2
// i=0 * 1 2 3 占位第一位
// i=1 * * 2 3 依次占位(得到数据)
// i=2 * * * 3 总共需要三次
for (int j = i; j < arr.length; j++) {
//如果每轮中找到比当前占位小的数就互换
if (arr[i] > arr[j]){
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
}
}
System.out.println(Arrays.toString(arr));
}
五、数组的内存图
1、java内存分配
java的内存被划分成五个部分:栈、堆、方法区、本地方法栈、寄存器。
方法区存放的是字节码文件(编译产生的class文件),也就是代码放在方法区。
栈内存是方法运行时进入的内存,例如main方法执行时会被调入进栈内存,定义的变量也在里面
堆内存 中 new出来的东西会在这块内存中开辟空间并产生地址。
第一步,java会将代码的.class文件加载到方法区,再将文件中的main方法提到栈内存中进行运行,main方法执行时会先运行第一行代码。
在栈内存中为a变量开辟一个区域存储数据,再在main方法中加载arr1变量的区域(等号左边),(等号右边)在堆内存中new了一个新的数组对象,用来存储数据,然后将数组的地址赋给arr1变量进行存储,由这个地址找到数组的存储位置调用数据。
再通过arr数组中的地址索引相应的位置进行修改和输出。
2、两个变量指向同一个数组
六、 数组使用常见错误
1、访问的元素位置超过最大索引,执行时会出现ArrayIndexOutOfBoundsException
(数组索引越界)
2、如果数组变量中没有存储数组的地址,而是null,在访问数组信息时会出现NullPointerException(空指针异常)
七、补充 二维数组
1、二维数组的定义格式
<数据类型> [ ][ ] 数组名 或者 <数据类型> 数组名[ ][ ]
int[][] score = new int[2][3];
第一个括号表示了整个二位数组的长度,第二个数组表示二维数组中存放的数组元素的长度;相当于一个一维数组中的存储的元素也是数组类型。
定义二维数组时必须定义最大维度,第一个括号中必须给定具体值。
int[][] score = new int[2][];
二维数组实际上就是一个以一维数组做为元素的一维数组。