一、数组介绍
什么是数组?
数组指的是一种容器,可以用来存储同种数据类型的多个值。
注:数组容器在存储数据的时候,需要结合隐式转换考虑
例如:int类型的数组容器(boolean、byte、short、int、double)
例如:double类型的数组容器(byte、short、int、long、float、double)
建议:容器的类型和存储的数据类型保持一致。
二、数组的定义与静态初始化
数组的定义
格式一:数据类型[] 数组名
范例:int[] array
格式二:数据类型 数组名[]
范例:int array[]
数组的静态初始化
初始化:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程
完整格式:数据类型[] 数组名 = new 数据类型[] {元素1,元素2,元素3……};
简单格式:数据类型[] 数组名 = {元素1,元素2,元素3……};
数组元素访问
格式:数组名[索引];
索引:也叫做下标,角标。
索引特点:从0开始,逐个+1增长,连续不间断。
数组的遍历
数组遍历:将数组中所有的内容取出来,取出来之后(打印,求和,判断……)
注:遍历指的是取出数据的过程,不要局限的理解为,遍历就是打印。
数组动态初始化
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值。
格式:数据类型[] 数组名 = new 数据类型[数组长度];
数组动态初始化和静态初始化的区别:
动态初始化:手动指定数组长度,由系统给出默认初始化值。(只明确元素个数,不明确具体数值,推荐使用动态初始化)
静态初始化:手动指定数组元素,系统会根据元素个数,计算出数组的长度。(需求中已经明确了要操作的具体数据,直接静态初始化即可)
数组常见问题
当访问了数组中不存在的索引,就会引发索引越界异常。
数组常见操作
求最值
需求:已知数组元素为{33,5,22,44,55},请找出数组中最大值并打印在控制台
代码如下:
public class ArrTest4 {
public static void main(String[] args) {
// 定义数组求最大值
// 1.定义数组用来存储5个值
int[] arr = { 33, 5, 22, 44, 55 };
// 2.定义一个变量max用来存储最大值
// 临时认为0索引的数据是最大的
int max = arr[0];
// 3.循环获取数组中的每一个元素
// 穿着每一个元素根max进行比较
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
System.out.println("最大值为:"+max);
}
}
运行结果为:

求和
需求:生成10个1~100之间的随机数存入数组。
1)求出所有数据的和
2)求所有数据的平均数
3)统计有多少个数据比平均值小
代码如下:
import java.util.Random;
public class ArrTest5 {
public static void main(String[] args) {
// 需求:生成10个1~100之间的随机数存入数组。
// 1)求出所有数据的和
// 2)求所有数据的平均数
// 3)统计有多少个数据比平均值小
// 1.定义数组
int[] arr = new int[10];
// 2.把随机数存入到数组当中
Random r = new Random();
for (int i = 0; i < arr.length; i++) {
// 每循环一次,就会生成一个新的随机数
int number = r.nextInt(100) + 1;
// 把生成的随机数添加到数组当中
// 数组名[索引]=数据
arr[i] = number;
}
System.out.println("随机生成的数为:");
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
// 1)求出所有数据的和
// 定义求和变量
int sum = 0;
for (int i = 0; i < arr.length; i++) {
// 循环得到每一个元素
// 并把元素累加到sum当中
sum = sum + arr[i];
}
System.out.println("数组中所有数据的和为:" + sum);
// 2)求所有数据的平均数
int avg = sum / arr.length;
System.out.println("数组中平均数为:" + avg);
// 3)统计有多少个数据比平均值小
int count = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] > avg) {
count++;
}
}
System.out.println("在数组中一共有" + count + "个数据比平均数小");
}
}
运行结果为:

交换数据
需求:定义一个数组,存入1,2,3,4,5。 按照要求交换索引对应的元素。
交换前: 1,2,3,4,5
交换后: 5,4,3,2,1
代码如下:
public class ArrTest6 {
public static void main(String[] args) {
// 需求:定义一个数组,存入1,2,3,4,5。 按照要求交换索引对应的元素。
// 交换前: 1,2,3,4,5
// 交换后: 5,4,3,2,1
// 1.定义数组存储数据
int[] arr= {1,2,3,4,5};
// 2.利用循环去交换数据
for(int i=0,j=arr.length-1;i<j;i++,j--) {
// 交换变量i和变量j指向的元素
int temp=arr[i];
arr[i]=arr[j];
arr[j]=temp;
}
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
}
}
运行结果为:

打乱数据
需求:定义一个数组,存入1~5。要求打乱数组中所有数据的顺序
代码如下:
import java.util.Random;
public class ArrTest7 {
public static void main(String[] args) {
// 需求:定义一个数组,存入1~5。要求打乱数组中所有数据的顺序。
// 1.定义数组存储1~5
int[] arr= {1,2,3,4,5};
// 2.循环遍历数组,从0索引开始打乱数据的顺序
Random r=new Random();
for(int i=0;i<arr.length;i++) {
// 生成一个随机索引
int randomIndex=r.nextInt(arr.length);
// 拿着随机索引指向的元素跟i指向的元素进行交换
int temp=arr[i];
arr[i]=arr[randomIndex];
arr[randomIndex]=temp;
}
for(int i=0;i<arr.length;i++) {
System.out.print(arr[i]+" ");
}
}
}
运行结果如下:

数组内存图
Java内存分配
栈: 方法运行时使用的内存,比如main方法运行,进入方法栈中执行。
程序的主入口(main方法)开始执行时会进栈,代码执行完毕会出栈
堆: 存储对象或者数组,new来创建的,都存储在堆内存。
new出来的东西会在这块内存中开辟空间并产生地址
方法区: 存储可以运行的class文件。
本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关。
寄存器: 给CPU使用,和我们开发无关。
注:从JDK8开始,取消方法区,新增元空间。把原来方法区的多种功能进行拆分,有的功能放到了堆中,有的功能放到了元空间中。
代码:
public static void main(String[] args) {
int a=10;
int b=10;
int c=a+b;
sout(c);
}
对应的内存分配为:(由于没有使用new,因此不会产生堆内存)

数组的内存图
public static void main(String[] args) {
int[] arr=new int[2];
sout(arr);
sout(arr[0]);
sout(arr[1]);
arr[0]=11;
arr[1]=22;
sout(arr[0]);
sout(arr[1]);
sout("----------");
int[] arr2= {33,44,55};
sout(arr2);
sout(arr2[0]);
sout(arr2[1]);
sout(arr2[2]);
}
该代码的内存图为:

总结:1.只要是new出来的一定是对立面开辟了一个小空间。
2.如果new了多次,那么在堆里面有多个小空间,每个小空间中都有各自的数据。
3.当两个数组指向同一个小空间时,其中一个数组对小空间中的值发生了改变,那么其数组再次访问的时候都是修改之后的结果了。