数组的定义格式:
格式一: 数据类型[] 变量名
例如: int[] ages
含义:定义一个整型数组,数组的名字叫ages。
格式二: 数据类型 变量名[]
例如: int ages[]
含义:定义一个整型数组,数组的名字叫ages。
推荐使用格式一。1. 便于理解;2.很多程序员都在使用格式一,便于阅读彼此的代码
格式二,是为了兼容C语言的写法,便于C程序员转型为Java程序员。
之前的课程讲过变量定义的三要素:数据类型 、变量名、初始值。
数组是一种数据类型,在定义数组变量的时候,也要为其指定初始值。数组的初始值指的是数组中每个元素的初始值。
数组的初始化分为2种:动态初始化 和 静态初始化。
动态初始化:在初始化数组时,只指定数组长度,由系统为其分配初始值。
数组长度:数组所能容纳的元素的个数。
数组元素的默认初始值
动态初始化格式:
数据类型[] 变量名 = new 数据类型[数组长度];
示例:
int[] ages = new int[10];
上述代码定义了一个int类型的数组,数组名是ages,数组的元素个数是10,每个元素都是int类型,每个元素的初始值是0。
等号左边:
int 表示数组中的元素是int类型。
[] 表示这是一个数组。
ages是数组名称,即变量名。
等号右边:
new 为数组申请堆区内存空间。申请的内存空间是连续的,内存空间的大小取决于元素类型和元素个数。
int 表示数组中的元素是int类型。
[]表示是一个数组,[10]表示数组能容纳10个数据。
因为是动态初始化,系统为每个int元素分配的初始值是0。
静态初始化:初始化数组时,人为指定每个元素的值。
格式一:
数据类型[] 变量名 = new 数据类型[]{数据1,数据2,数据3,...};
格式一示例:
int[] ages = new int[]{3, 4, 4, 3, 2, 4, 3, 4, 3, 3};
上述代码定义了一个int数组,数组名是ages,数组中包含10个int数据。它们的初始值不再是系统默认给的0,而是我们人为指定的初始值。
等号左边:
int 表示数据元素是int类型。
[] 表示这是一个数组。
ages是数组名,即变量名。
等号右边:
new 为数组申请堆内存空间。申请的内存空间是连续的,内存空间的大小取决于元素类型和元素个数。
int 表示数组中的元素是 int类型。
[] 表示这是一个数组。-----注意不要写元素个数。
{3, 4, 4, 3, 2, 4, 3, 4, 3, 3} 表示数组中每个元素的初始值。大括号中写了几个值,数组的元素个数就是几。
格式二:-----格式二是格式1的简化格式,通常使用这种格式。
数据类型[] 变量名 = {数据1, 数据2, 数据3,...};
格式二示例:
int[] ages = {3, 4, 4, 3, 2, 4, 3, 4, 3, 3}
格式二定义的数组和格式一含义一样,只是格式一的简化形式。
数组的访问包括:数组的访问、数组元素的访问。
数组在内存中是一段连续的内存区域。
数组名是一个变量,但是它不存储具体数据,存储的是这段连续内存区域的起始地址(也叫首地址)。
数组名代表的是整个数组,不代表数组中的元素。
数组变量的访问方式:数组名
在打印数组变量的时候,会打印出数组所存储的内存地址。
格式:数组名[索引]
索引指的是数据的序号(编号),通常也称为数组的下标。在Java中数组下标是从0开始的。即第1个数据下标为0,第2个数据下标为1,第3个数据下标为2,...
数组名[索引] 等同于一个变量,是一种特殊的变量名。
索引的最小值是:0,索引的最大值是:元素个数 - 1
数组元素的访问包括:给数组元素的赋值、使用数组元素的值。
public static void main(String[] args) {
int[] ages = {3, 4, 3, 2, 5};
System.out.println(ages[0]);
ages[0] = 7;//此处将ages[0]的值赋值为7,会覆盖原有的3
System.out.println(ages[0]);
}
public static void main(String[] args) {
int[] ages = {3, 4, 3, 2, 5};
System.out.println(ages[0]);
ages[0] = 7;//此处将ages[0]的值赋值为7
System.out.println(ages[0]);
int num = ages[1];//将ages[1]赋值给变量num
int sum = ages[2] + ages[3];//将ages[2]于ages[3]的和赋值给sum
System.out.println(num);
System.out.println(sum);
}
数组名代表的是整个数组,存储的是数组的起始地址。
数组元素是数组中真正的数据,数组元素的访问方式是 数组名[索引]
索引的最小值是:0,最大值是:元素个数-1
数组名代表的是整个数组,存储的是数组的起始地址。
数组元素是数组中真正的数据,数组元素的访问方式是 数组名[索引]
索引的最小值是:0,最大值是:元素个数-1
数组名代表的是整个数组,存储的是数组的起始地址。
数组元素是数组中真正的数据,数组元素的访问方式是 数组名[索引]
索引的最小值是:0,最大值是:元素个数-1
Java语言对内存做了若干个分区,最为重要的2个分区是:堆区和栈区。
栈区:用于存放局部变量的内存区域。
局部变量:方法内定义的变量,包括方法的参数。
栈区由系统管理,系统为每个变量分配一个区域。以栈的方式管理变量的生命周期。
堆区:唯一一个程序员可以操作和使用的内存区域。
堆区必须通过new来开辟空间。
程序员只负责开辟和使用堆区空间,Java的垃圾回收机制会在堆区内存不再使用的时候,回收开辟的区域。
public static void main(String[] args) {
//array变量是局部变量,array变量存放在栈区,有系统管理array变量的生命周期。
//虽然array自己存放在栈区,但是array变量的值 是数组的起始地址,存的是new新开辟的12个字节的首地址。
int[] array = new int[3];
System.out.println(array);//此处打印的是数组的起始地址(堆区)
System.out.println(array[0]);// 0
System.out.println(array[1]);// 0
System.out.println(array[2]);// 0
array[0] = 20;//数组元素的赋值
array[2] = 10;//数组元素的赋值
array[1] = array[0] + array[2];//数组元素的赋值
System.out.println(array[0]);// 20
System.out.println(array[1]);// 30
System.out.println(array[2]);// 10
}
下面是创建数组array的内存分配图:
对于 int[] array = new int[3];这行代码,可以细分为4个步骤:
定义局部变量array,数据类型是 int[],局部变量被存放在了内存的栈区。对应代码:int[] array
通过new关键字,在堆区开辟一段连续的内存空间,开辟的空间大小是12个字节。这段内存空间的首地址是15db9742。之所以开辟12个字节,是因为需要存放3个int数据,每个int是4个字节,所以是12个字节。
系统为数组的3个元素设置默认值0。因为是动态初始化,所以系统来设置默认初始值,int类型元素的初始值默认是0。-----步骤2和3对应的代码是: new int[3]
将数组的首地址赋值给变量array,因此array的值是地址15db9742
因此执行下面4行代码时
System.out.println(array);//此处打印的是数组的起始地址(堆区),即15db9742
System.out.println(array[0]);// 0
System.out.println(array[1]);// 0
System.out.println(array[2]);// 0
打印的结果分别是:
[I@15db9742 0 0 0
下面6行代码是给数组元素赋值,并打印元素的值。
array[0] = 20;//数组元素的赋值
array[2] = 10;//数组元素的赋值
array[1] = array[0] + array[2];//数组元素的赋值
System.out.println(array[0]);// 20
System.out.println(array[1]);// 30
System.out.println(array[2]);// 10
下面是数组元素赋值的内存示意图:
array[0] = 20; 这是一行赋值语句,把数据20赋值给数组的第1个元素,第1个元素就是数组下标为0的元素。赋值之后,元素的值由0变成了20。数组名[索引]可以看成是一个变量。
array[2] = 10;这行也是一条赋值语句,把数据10赋值给数组的第3个元素,第3个元素就是数组下标为2的元素。赋值之后,元素的值由0变成了10。数组名[索引]可以看成是一个变量。
array[1] = array[0] + array[2]; 这一行仍然是赋值语句,计算array[0] + array[2]的值,将结果赋值给array[1]。即 20 + 10的值30赋值给array[1],赋值之后,元素的值变为30。数组名[索引]可以看成是一个变量。
所以当执行打印语句的时候,打印的结果分别是:20、30、10
System.out.println(array[0]);// 20
System.out.println(array[1]);// 30
System.out.println(array[2]);// 10
public static void main(String[] args) {
int num = 0;
int sum = 0;
int[] array = {10,20,30};//new int[]{10,20,30};
num = array[0] * array[2] / array[1];
sum = array[0] + array[1] + array[2];
System.out.println(num);
System.out.println(sum);
}
局部变量存放在栈区,num、sum、array都是局部变量,因此他们存放在栈区。new开辟的内存在堆区。
下面是定义变量num,sum,array时的内存分配情况:
int num = 0; 定义了一个局部变量num,num的初始值是0。局部变量num被存放在了内存的栈区。如上图所示。
int sum = 0;定义了一个局部变量sum,sum的初始值是0。局部变量sum被存放在了内存的栈区。如图所示。
int[] array 定义了一个局部变量array,array的值最终会保存堆区数组的首地址。栈区采用先进后出的方式来管理,即先定义的局部变量在栈底,后定义的局部变量再栈顶。
{10, 20, 30}是数组静态初始化的简写模式,完整的写法是 new int[]{10, 20, 30}。new关键字在堆区开辟了12个字节的内存,用于存放3个int数据,数组的首地址是15db9742。
数组一共包含3个int元素,元素的初始值分别是10(array[0])、20(array[1])、30(array[2])。
将数组的首地址15db9742赋值给array变量。即array的值是15db9742。
num = array[0] * array[2] / array[1];
sum = array[0] + array[1] + array[2];
System.out.println(num);
System.out.println(sum);
修改num和sum值的内存图:
num = array[0] * array[2] / array[1]; 即 10 * 30 / 20,将结果15赋值给变量num。所以在内存中num的值由0变为了15。
sum = array[0] + array[1] + array[2]; 即 10 + 20 + 30,将结果60赋值给变量sum。所以内存中sum的值由0变为了60。
所以打印num和sum的值,分别是15和60。
public static void main(String[] args) {
int[] arr1 = new int[2];
int[] arr2 = {15, 10, 20};
System.out.println(arr1);//第一个数组堆区内存地址15db9742
System.out.println(arr1[0]);// 0
System.out.println(arr1[1]);// 0
System.out.println(arr2);//第二个数组堆区内存地址6d06d69c
System.out.println(arr2[0]);// 15
System.out.println(arr2[1]);// 10
System.out.println(arr2[2]);// 20
arr1[0] = 50;
arr1[1] = arr1[0] + arr2[0]; //65
arr2[2] = 28;
System.out.println(arr1);//第一个数组堆区内存地址15db9742
System.out.println(arr1[0]);// 50
System.out.println(arr1[1]);// 65
System.out.println(arr2);//第二个数组堆区内存地址6d06d69c
System.out.println(arr2[0]);// 15
System.out.println(arr2[1]);// 10
System.out.println(arr2[2]);// 28
}
上述代码的输出结果:
数组arr1、arr2内存分配情况:
对于int[] arr1 = new int[2];可以分解为4个步骤:
定义局部变量arr1,数据类型是 int[],局部变量被存放在了内存的栈区。对应代码:int[] arr1
通过new关键字,在堆区开辟一段连续的内存空间,开辟的空间大小是8个字节。这段内存空间的首地址是15db9742。之所以开辟8个字节,是因为需要存放2个int数据,每个int是4个字节,所以是8个字节。
系统为数组的2个元素设置默认值0。因为是动态初始化,所以系统来设置默认初始值,int类型元素的初始值默认是0。-----步骤2和3对应的代码是: new int[2]
将数组的首地址赋值给变量arr1,因此arr1的值是地址15db9742
对于int[] arr2 = {15, 10, 20};等价于 int[] arr2 = new int[]{15, 10, 20};仍然可以分解为4个步骤:
定义局部变量arr2,数据类型是 int[],局部变量被存放在了内存的栈区。对应代码:int[] arr2
通过new关键字,在堆区开辟一段连续的内存空间,开辟的空间大小是12个字节。这段内存空间的首地址是6d06d69c。之所以开辟12个字节,是因为需要存放3个int数据,每个int是4个字节,所以是12个字节。
为3个数组元素分别赋初始值15,10,20。-----步骤2和3对应的代码是: {15, 10, 20}
将数组的首地址赋值给变量arr2,因此arr2的值是地址6d06d69c
System.out.println(arr1);//第一个数组堆区内存地址15db9742
System.out.println(arr1[0]);// 0
System.out.println(arr1[1]);// 0
System.out.println(arr2);//第二个数组堆区内存地址6d06d69c
System.out.println(arr2[0]);// 15
System.out.println(arr2[1]);// 10
System.out.println(arr2[2]);// 20
上述7行打印的结果是:
修改数组arr1、arr2元素值:
arr1[0] = 50;
arr1[1] = arr1[0] + arr2[0]; //65
arr2[2] = 28;
修改数组元素的内存图如下:
arr1[0] = 50; 这行代码的作用是给arr1下标为0的元素(即arr1的第1个元素)赋值,将arr1[0]的值修改成50。
arr1[1] = arr1[0] + arr2[0]; 这行代码的作用是给arr1下标为1的元素(即arr1的第2个元素)赋值,将arr1[1]的值修改成65(即 50 + 15)。
arr2[2] = 28;这行代码的作用是给arr2下标为2的元素(即arr2的第3个元素)赋值,将arr2[2]的值修改成28。
System.out.println(arr1);//第一个数组堆区内存地址15db9742
System.out.println(arr1[0]);// 50
System.out.println(arr1[1]);// 65
System.out.println(arr2);//第二个数组堆区内存地址6d06d69c
System.out.println(arr2[0]);// 15
System.out.println(arr2[1]);// 10
System.out.println(arr2[2]);// 28
上述7行打印的结果是:
public static void main(String[] args) {
int[] arr1 = {25, 13, 36};
int[] arr2 = arr1;//将arr1的值赋值给arr2,即arr2和arr1保存了相同的堆区地址。
System.out.println(arr1);// arr1保存的内存地址是15db9742
System.out.println(arr2);// arr2保存的内存地址是15db9742
System.out.println(arr1[0]);// 25
System.out.println(arr2[0]);// 25
System.out.println(arr1[1]);// 13
System.out.println(arr2[1]);// 13
arr1[0] = 100;
arr2[1] = 200;
System.out.println(arr1);// arr1保存的内存地址是15db9742
System.out.println(arr2);// arr2保存的内存地址是15db9742
System.out.println(arr1[0]);// 100
System.out.println(arr2[0]);// 100
System.out.println(arr1[1]);// 200
System.out.println(arr2[1]);// 200
}
上述代码输出的结果:
数组arr1、arr2内存分配情况:
int[] arr1 = {25, 13, 36}; 的完整格式是: int[] arr1 = new int[]{25, 13, 36};这行代码可以分为4个步骤:
定义局部变量arr1,数据类型是 int[],局部变量被存放在了内存的栈区。对应代码:int[] arr1
通过new关键字,在堆区开辟一段连续的内存空间,开辟的空间大小是12个字节。这段内存空间的首地址是15db9742。之所以开辟12个字节,是因为需要存放3个int数据,每个int是4个字节,所以是12个字节。
为3个数组元素分别赋初始值25,13,36。-----步骤2和3对应的代码是: {25, 13, 36}
将数组的首地址赋值给变量arr1,因此arr1的值是地址15db9742
int[] arr2 = arr1; 这是一行赋值语句。这行代码可以分为2个步骤:
定义局部变量arr2,数据类型是int[],局部变量存放在了内存的栈区。对应代码:int[] arr2
将变量arr1的值赋值给变量arr2。因为arr1里存放的是堆区地址15db9742,因此赋值以后,arr2的值也是15db9742。相当于有2个数组变量指向了同一块内存区域。所以无论通过arr1访问数组元素还是通过arr2访问数组元素都会得到相同的数据。
System.out.println(arr1);// arr1保存的内存地址是15db9742
System.out.println(arr2);// arr2保存的内存地址是15db9742
System.out.println(arr1[0]);// 25
System.out.println(arr2[0]);// 25
System.out.println(arr1[1]);// 13
System.out.println(arr2[1]);// 13
上述6行代码打印的结果如下:
修改数组元素值的内存图如下:
arr1[0] = 100; 通过数组arr1修改了堆区内存中的数据。因为arr2和arr1指向的是相同的内存区域,所以arr2[0]的值也是100。
arr2[1] = 200; 通过数组arr2修改了堆区内存中的数据。因为arr1和arr2指向的是相同的内存区域,所以arr1[1]的值也是200。
System.out.println(arr1);// arr1保存的内存地址是15db9742
System.out.println(arr2);// arr2保存的内存地址是15db9742
System.out.println(arr1[0]);// 100
System.out.println(arr2[0]);// 100
System.out.println(arr1[1]);// 200
System.out.println(arr2[1]);// 200
上述6行代码打印的结果如下:
数组变量存放的是堆区的数组的首地址。数组变量本身存放在栈区,它的值是堆区的地址。
数组元素存放在堆区,通过 数组名[索引]的方式可以访问数组元素。
给数组变量赋值,相当于改变了数组变量的指向。
如果多个数组变量指向了同一个数组,可以通过任意一个数组变量修改数组元素的值。
数组下标越界:指的是数组下标的值超出了下标的取值范围。
数组下标的取值范围:0 ~ 数组个数 - 1
例如:
int[] arr = new int[3];
System.out.println(arr);
System.out.println(arr[3]);//此处会产生数组越界问题。数组下标的取值范围是[0, 2],但访问了下标为3的元素。
上面代码运行后,会出现如下结果:
图中报出了一个异常(Exception),异常的意思是数组的索引超出了边界。下标3超出了下标的范围。简单说就是数组的下标越界。
int[] arr = new int[3]; 可以分解为4个步骤:
定义局部变量arr,数据类型是 int[],局部变量被存放在了内存的栈区。对应代码:int[] arr
通过new关键字,在堆区开辟一段连续的内存空间,开辟的空间大小是12个字节。这段内存空间的首地址是15db9742。之所以开辟12个字节,是因为需要存放3个int数据,每个int是4个字节,所以是12个字节。
系统为数组的3个元素设置默认值0。因为是动态初始化,所以系统来设置默认初始值,int类型元素的初始值默认是0。-----步骤2和3对应的代码是: new int[3]
将数组的首地址赋值给变量arr,因此arr的值是地址15db9742
System.out.println(arr[3]); 这行代码的作用是打印数组下标为3的元素的值,通过上面的图,我们会发现,数组只有3个元素,对应的下标分别是0,1,2。现在要访问下标为3的元素,3超出了数组下标的范围,所以程序会出现异常。开发中应避免出现数组越界的问题。
null是一个常量,用于给引用类型变量赋值。
空指针异常:指的是数组(或对象)指向了一个空地址,如果指向了空地址以后,还在继续访问数据,就会出现空指针异常。
课程知识回顾:
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);// arr的值是15db9742
arr = null;// 将arr设置为null,即空值(内存地址为0的值)
System.out.println(arr);// null
System.out.println(arr[0]); //空指针异常
}
上面代码运行的结果是:
图中报出了一个异常,异常的意思是空指针异常。出现这种问题的原因就是,数组变量保存的地址已经被清空,数组已不再指向以前的堆区,所以访问数据的时候,就会出现异常。
int[] arr = new int[3]; 可以分解为4个步骤:
定义局部变量arr,数据类型是 int[],局部变量被存放在了内存的栈区。对应代码:int[] arr
通过new关键字,在堆区开辟一段连续的内存空间,开辟的空间大小是12个字节。这段内存空间的首地址是15db9742。之所以开辟12个字节,是因为需要存放3个int数据,每个int是4个字节,所以是12个字节。
系统为数组的3个元素设置默认值0。因为是动态初始化,所以系统来设置默认初始值,int类型元素的初始值默认是0。-----步骤2和3对应的代码是: new int[3]
将数组的首地址赋值给变量arr,因此arr的值是地址15db9742
arr = null; 执行之后,arr中原有的值15db9742被清空。无法再指向堆区的数组元素。
System.out.println(arr[0]); 这行代码中的 arr[0]出现了异常,原因就是arr已经不再指向任何(有效的)内存地址,所以操作数据的时候,会出现空指针异常。
数组的遍历:指的是获取数组中的每个元素。
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
System.out.println(arr[4]);
}
上述代码的作用就是遍历并打印每个数组元素的值。这段代码虽然能达到遍历的效果,但是代码质量不高,如果数组有100万条数据,输出语句需要写100万行。
通过观察上述代码,你会发现明显的规律:每条打印语句唯一的区别就是数组的下标不同。下标从0开始,每次下标增1,直到数组个数-1。因此可以使用for循环对数组进行遍历。
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
for(int i = 0; i < 5; i++) {
System.out.println(arr[i]);
}
}
上面的代码就是简化之后的数组遍历代码。仔细观察不难发现,i 的初始值 0,可以对应数组第 1 个元素的下标0,每循环一次,执行一次 i++, 可以让 i 的值增 1,这样能对应数组的每一个下标。直到 i 的值达到数组元素个数-1,即 i < 数组元素个数。
由于数组元素个数这么重要,所以Java提供了获取数组元素个数的的方式。
格式:数组名.length
示例:arr.length
鉴于此,上述代码可以进一步优化。
public static void main(String[] args) {
int[] arr = {10, 20, 30, 40, 50};
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
因为每个数组的元素个数,都可以通过数组名.length获得,所以任意一个数组的遍历都可以写成如下形式:
public static void main(String[] args) {
int[] 数组名 = {...};
for(int i = 0; i < 数组名.length; i++) {
数组名[i];//对 数组名[i] 进行操作
}
}
public static void main(String[] args) {
int[] arr = {111, 222, 333, 444};
//数组arr的遍历
for(int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
int[] arr2 = {35, 12, 16, 24, 76, 88, 31};
//数组arr2的遍历
for(int i = 0; i < arr2.length; i++) {
System.out.println(arr2[i]);
}
}
需求:有一组数据 10,8,23,41,52,66,34,12。编写代码求出数组中的最大值。
代码:
public static void main(String[] args) {
//需求:有一组数据 10,8,23,41,52,66,34,12。
//编写代码求出数组中的最大值。
//分析:
//1. 这组数据使用 int 数组来保存。---数组的定义、数组的静态初始化。
//2. 定义一个变量 max,用于保存数组中最大的元素。
//3. 遍历数组,让 max 依次和数组中的每个元素比较,如果元素大于max,将max值更新为元素的值。
//4. 一趟循环结束后,max中保存的就是数组中的最大值。
int[] array = {10, 8, 23, 41, 52, 66, 34, 12};
int max = 0;
for(int i = 0; i < array.length; i++) {
if(array[i] > max) {
max = array[i];
}
}
System.out.println("max = " + max);
}
需求:有一组数据 10,8,23,41,52,66,34,12。编写代码求出数组中的最小值。
代码:
public static void main(String[] args) {
//需求:有一组数据 10,8,23,41,52,66,34,12。
//编写代码求出数组中的最小值。
//分析:
//1. 这组数据使用 int 数组来保存。---数组的定义、数组的静态初始化。
//2. 定义一个变量 min,用于保存数组中最小的元素。---注意 min的初始值要高于数组最大元素的值。
//3. 遍历数组,让 min 依次和数组中的每个元素比较,如果元素小于min,将min值更新为元素的值。
//4. 一趟循环结束后,min中保存的就是数组中的最小值。
int[] array = {10, 8, 23, 41, 52, 66, 34, 12};
int min = 100;
for(int i = 0; i < array.length; i++) {
if(array[i] < min) {
min = array[i];
}
}
System.out.println("min = " + min);
}
需求:有一组数据 10,8,23,41,52,66,34,12。编写代码求出数组中的最大值以及最大值的下标。
代码:
public static void main(String[] args) {
//需求:有一组数据 10,8,23,41,52,66,34,12。
//编写代码求出数组中的最大值以及最大值的下标。
//分析:
//1. 这组数据使用 int 数组来保存。---数组的定义、数组的静态初始化。
//2. 定义一个变量 max,用于保存数组中最大的元素。定义一个变量index,用于保存数组中最大元素的下标。
//3. 遍历数组,让 max 依次和数组中的每个元素比较,如果元素大于max,将max值更新为元素的值,同时将index的值更新为i的值。
//4. 一趟循环结束后,max中保存的就是数组中的最大值,index中保存的就是最大值的下标。
int[] array = {10, 8, 23, 41, 52, 66, 34, 12};
int max = 0;
int index = 0;
for(int i = 0; i < array.length; i++) {
if(array[i] > max) {
max = array[i];
index = i;
}
}
System.out.println("max = " + max + " , index = " + index);
}
需求:有一组数据 10,8,23,41,52,66,34,12。编写代码求出数组中的最小值以及最小值的下标。
代码:
public static void main(String[] args) {
//需求:有一组数据 10,8,23,41,52,66,34,12。
//编写代码求出数组中的最小值以及最小值的下标。
//分析:
//1. 这组数据使用 int 数组来保存。---数组的定义、数组的静态初始化。
//2. 定义一个变量 min,用于保存数组中最小的元素。定义一个变量index,用于保存数组中最小元素的下标。---注意 min的初始值要大于数组中最大元素的值
//3. 遍历数组,让 min 依次和数组中的每个元素比较,如果元素小于min,将min值更新为元素的值,同时将index的值更新为i的值。
//4. 一趟循环结束后,min中保存的就是数组中的最小值,index中保存的就是最小值的下标。
int[] array = {10, 8, 23, 41, 52, 66, 34, 12};
int min = 100;
int index = 0;
for(int i = 0; i < array.length; i++) {
if(array[i] < min) {
min = array[i];
index = i;
}
}
System.out.println("min = " + min + " , index = " + index);
}
需求:有一组数据 10,8,23,41,52,66,34,12。编写代码求出数组中的最大值,最小值,最大值下标,最小值下标。
代码:
public static void main(String[] args) {
//需求:有一组数据 10,8,23,41,52,66,34,12。
//编写代码求出数组中的最大值,最小值,最大值下标,最小值下标。
//分析:
//1. 这组数据使用 int 数组来保存。---数组的定义、数组的静态初始化。
//2. 定义一个变量max,用于保存数组中最大的元素;定义一个变量 min,用于保存数组中最小的元素。
//定义一个变量indexOfMax,用于保存数组中最大元素的下标,定义一个变量indexOfMin,用于保存数组最小元素的下标。---注意 min的初始值要大于数组中最大元素的值
//3. 遍历数组,遍历的过程中让 max 依次和数组中的每个元素比较,如果元素大于max,将max值更新为元素的值,同时将indexOfMax的值更新为i的值;
//同样,在遍历的过程在让 min 依次和数组中的每个元素比较,如果元素小于min,将min值更新为元素的值,同时将indexOfMin的值更新为i的值。
//4. 一趟循环结束后,max中保存的就是数组中的最大值,indexOfMax中保存的就是最大值的下标。min中保存的就是数组中的最小值,indexOfMin中保存的就是最小值的下标。
int[] array = {10, 8, 23, 41, 52, 66, 34, 12};
int max = 0;
int min = 100;
int indexOfMax = 0;
int indexOfMin = 0;
for(int i = 0; i < array.length; i++) {
if(array[i] > max) {
max = array[i];
indexOfMax = i;
}
if(array[i] < min) {
min = array[i];
indexOfMin = i;
}
}
System.out.println("max = " + max + " , indexOfMax = " + indexOfMax);
System.out.println("min = " + min + " , indexOfMin = " + indexOfMin);
}
需求:有一个具有5个 int 数据的数组,数组中的每个元素都是[10, 100]之间的随机数。编写代码求出数组中的最大值,最小值,最大值下标,最小值下标。
代码:
public static void main(String[] args) {
//需求:有一个具有5个 int 数据的数组,数组中的每个元素都是[10, 100]之间的随机数。
//编写代码求出数组中的最大值,最小值,最大值下标,最小值下标。
//分析:
//1. 这组数据使用 int 数组来保存。---数组的定义、数组的动态初始化。
//2. 定义一个变量max,用于保存数组中最大的元素;定义一个变量 min,用于保存数组中最小的元素。
//定义一个变量indexOfMax,用于保存数组中最大元素的下标,定义一个变量indexOfMin,用于保存数组最小元素的下标。---注意 min的初始值要大于数组中最大元素的值
//3. 循环为数组的每个元素赋值一个随机数。--需要在循环之前创建Random对象。
//4. 遍历数组(或在循环为数组元素赋值的过程中),遍历的过程中让 max 依次和数组中的每个元素比较,如果元素大于max,将max值更新为元素的值,同时将indexOfMax的值更新为i的值;
//同样,在遍历的过程在让 min 依次和数组中的每个元素比较,如果元素小于min,将min值更新为元素的值,同时将indexOfMin的值更新为i的值。
//4. 一趟循环结束后,max中保存的就是数组中的最大值,indexOfMax中保存的就是最大值的下标。min中保存的就是数组中的最小值,indexOfMin中保存的就是最小值的下标。
int[] array = new int[5];
int max = 0;
int min = 100;
int indexOfMax = 0;
int indexOfMin = 0;
Random random = new Random();
for(int i = 0; i < array.length; i++) {
array[i] = random.nextInt(100 - 10 + 1) + 10;
System.out.print(array[i] + " ");
if(array[i] > max) {
max = array[i];
indexOfMax = i;
}
if(array[i] < min) {
min = array[i];
indexOfMin = i;
}
}
System.out.println();
System.out.println("max = " + max + " , indexOfMax = " + indexOfMax);
System.out.println("min = " + min + " , indexOfMin = " + indexOfMin);
}
需求:有一个具有5个 int 数据的数组,数组中的每个元素都是[10, 30]之间的随机数。编写代码求出数组中的元素的和以及元素的平均值,打印出所有高于平均值的数,打印出所有低于平均值的数。
代码:
public static void main(String[] args) {
//需求:有一个具有5个 int 数据的数组,数组中的每个元素都是[10, 30]之间的随机数。
//编写代码求出数组中的元素的和以及元素的平均值,打印出所有高于平均值的数,打印出所有低于平均值的数。
//分析:
//1. 定义一个数组,使用动态初始化为数组赋初始值。
//2. 定义一个变量sum保存元素的和,定义一个变量avg保存数组元素的平均值---平均值变量使用double类型。
//3. 通过循环为每个元素赋值,数组元素的值在[10,30]之间。---循环之前先创建Random对象。
//4. 在循环的过程中,计算元素的和。
//5. 循环结束后,计算元素的平均值。
//6. 遍历数组,打印所有大于平均数的数组元素。
//7. 遍历数组,打印所有小于平均数的数组元素。
int[] array = new int[5];
int sum = 0;
double avg = 0.0;
Random random = new Random();
for(int i = 0; i < array.length; i++) {
array[i] = random.nextInt(30 - 10 + 1) + 10;
System.out.print(array[i] + " ");
sum += array[i];
}
System.out.println();
avg = sum * 1.0 / array.length;
System.out.println("sum = " + sum + ", avg = " + avg);
System.out.print("比平均数大的数是:");
for(int i = 0; i < array.length; i++) {
if(array[i] > avg) {
System.out.print(array[i] + " ");
}
}
System.out.println();
System.out.print("比平均数小的数是:");
for(int i = 0; i < array.length; i++) {
if(array[i] < avg) {
System.out.print(array[i] + " ");
}
}
System.out.println();
}
需求:有一个包含10个元素的数组,每个元素的值在[10,30]之间,查找数组中是否包含18,如果有18,打印出值为18的元素的下标。如果没有18,打印“数组中不包含18”。
代码:
public static void main(String[] args) {
//需求:有一个包含10个元素的数组,每个元素的值在[10,30]之间,
//查找数组中是否包含18,如果有18,打印出值为18的元素的下标。如果没有18,打印“数组中不包含18”。
//分析:
//1. 定义一个int数组,使用动态初始化为数组赋初始值。
//2. 创建Random对象
//3. 通过循环为每个数组元素赋值
//4. 定义一个boolean类型变量isContain,初始值设置为false,用于记录数组是否包含18,如果包含18,变量值设置为true。
//5. 遍历数组中的元素,判断是否包含18,如果包含18,将isContain设置为true,并结束循环。
//6. 如果遍历数组后,isContain仍然为false,表示数组中不包含18.
int[] array = new int[10];
Random random = new Random();
for(int i = 0; i < array.length; i++) {
array[i] = random.nextInt(30 - 10 + 1) + 10;
System.out.print(array[i] + " ");
}
System.out.println();
boolean isContain = false;
for(int i = 0; i < array.length; i++) {
if(array[i] == 18) {
isContain = true;
break;
}
}
if(isContain == false) {
System.out.println("数组中不包含18.");
}else {
System.out.print("数组中包含18。值为18的元素的下标是:");
for(int i = 0; i < array.length; i++) {
if(array[i] == 18) {
System.out.print(i + " ");
}
}
}
}
需求:有一组已经排好顺序的数据:5,13,19,21,37,56,64,75,80,88,92。编写代码查询数组中是否包含数据21。
代码:(普通的查找方式---顺序查找)
public static void main(String[] args) {
//需求:有一组已经排好顺序的数据:5,13,19,21,37,56,64,75,80,88,92。
//编写代码查询数组中是否包含数据21。
//方法一:普通查找方式
int[] array = {5, 13, 19, 21, 37, 56, 64, 75, 80, 88, 92};
int num = 21;
boolean isContain = false;
for(int i = 0; i < array.length; i++) {
if(array[i] == num) {
isContain = true;
break;
}
}
if(isContain == true) {
System.out.println("查到了数据:" + num);
}else {
System.out.println("数组中没有数据:" + num);
}
}
代码:(折半查找方式)
折半查找也叫二分查找。它是一种效率较高的查找方法。但是折半查找要求数据必须有序(升序或者降序)。
折半查找的思想:
定义3个变量分别保存第一个元素(low),最后一个元素(high)以及中间元素的下标(mid),mid = (low + high) / 2。
判断中间元素是否是目标数据,如果是目标数据,表示找到数据;
如果中间元素大于目标数据,说明目标数据在第一个元素和中间元素之间。将high改为mid - 1,更新mid的值(mid = (low + high) / 2);
如果中间元素小于目标数据,说明目标数据在中间元素和最后一个元素之间。将low改为mid + 1,更新mid的值(mid = (low + high) / 2);
继续判断中间元素是否是目标数据,如果是目标数据,表示找到数据;
如果中间元素大于目标数据,说明目标数据在第一个元素和中间元素之间。将high改为mid - 1,更新mid的值(mid = (low + high) / 2);
如果中间元素小于目标数据,说明目标数据在中间元素和最后一个元素之间。将low改为mid + 1,更新mid的值(mid = (low + high) / 2);
重复上述步骤,直到 low > high为止。(或者中间找到了数据)
以查找数据21(目标数据)为例,折半查找的过程如下:
目标数据21和中间数据56相比,由于 56 > 21,所以将high改为mid - 1,mid改为(low + high) / 2
目标数据21和中间数据19相比,由于19 < 21,所以将low改为mid + 1,mid改为(low + high) / 2
目标数据21和中间数据21相比,数据相等,结束查找。
public static void main(String[] args) {
//需求:有一组已经排好顺序的数据:5,13,19,21,37,56,64,75,80,88,92。
//编写代码查询数组中是否包含数据78,21,13。
//方法二:折半查找方式
int[] array = {5, 13, 19, 21, 37, 56, 64, 75, 80, 88, 92};
int num = 21;
boolean isContain = false;
int low = 0;
int high = array.length - 1;
int mid = (low + high) / 2;
while(low <= high) {
if(array[mid] == num) {
isContain = true;
break;
}else if(array[mid] > num) {
high = mid - 1;
mid = (low + high) / 2;
}else {
low = mid + 1;
mid = (low + high) / 2;
}
}
if(isContain == true) {
System.out.println("查到了数据:" + num);
}else {
System.out.println("数组中没有数据:" + num);
}
}
数组相等指的是数组长度相等,并且对应下标的元素也相等。即判断数组相等的指标有2个:1.数组长度相等;2.对应位置的元素相等。
需求:有2个数组数据分别是:{15, 7, 22, 13, 40} , {15, 7, 22, 15, 40},编写代码判断数组是否相等。
代码:
public static void main(String[] args) {
//需求:有2个数组数据分别是:{15, 7, 22, 13, 40} , {15, 7, 22, 15, 40},
//编写代码判断数组是否相等。
int[] arr1 = {15, 7, 22, 13, 40};
int[] arr2 = {15, 7, 22, 15, 40};
int length1 = arr1.length;
int length2 = arr2.length;
boolean isEqual = true;
if(length1 == length2) {
//如果数组元素个数相等,再判断 对应位置的元素是否相同。
for(int i = 0; i < length1; i++) {
if(arr1[i] != arr2[i]) {
isEqual = false;
break;
}
}
}else {
isEqual = false;
}
if(isEqual == true) {
System.out.println("两个数组相等");
}else {
System.out.println("数组不相等");
}
}
数组的拷贝,涉及到2个数组,一个是源数组,一个是目的数组,将源数组的数据拷贝到目的数组中。目的数组的容量(数组长度)要大于等于源数组的容量。所谓的拷贝,就是把源数组下标为0的元素赋值给目的数组下标为0的元素,把源数组下标为1的元素赋值给目的数组下标为1的元素,....,把源数组下标为length-1的元素赋值给目的数组下标为length-1的元素,
需求:创建一个包含10个随机数的数组(源数组),随机数的取值范围是[10, 80],将数组中的数据拷贝到一个新的数组中。
代码:
public static void main(String[] args) {
//需求:创建一个包含10个随机数的数组(源数组),随机数的取值范围是[10, 80],
//将数组中的数据拷贝到一个新的数组中。
//分析:
//1. 创建2个数组,一个数组用于保存10个随机数,另外一个数组用于保存拷贝后的数据,--数组的定义,动态初始化
//2. 创建Random对象
//3. 通过循环产生10个随机数,并输出10个数的值
//4. 编写循环实现拷贝
//5. 打印拷贝结果
int[] sourceArray = new int[10];
int[] destinationArray = new int[sourceArray.length];
Random random = new Random();
for(int i = 0; i < sourceArray.length; i++) {
sourceArray[i] = random.nextInt(80 - 10 + 1) + 10;
System.out.print(sourceArray[i] + " ");
}
System.out.println();
//实现拷贝
for(int i = 0; i < sourceArray.length; i++) {
destinationArray[i] = sourceArray[i];
}
//打印拷贝结果
for(int i = 0; i < destinationArray.length; i++) {
System.out.print(destinationArray[i] + " ");
}
System.out.println();
}
数组的翻转指的是:数组元素颠倒一下,即数组第一个元素和最后一个元素互换,第二个元素和倒数第二个元素互换,...
需求:创建一个包含10个随机数的数组,每个随机数的范围是[10, 80],实现数组元素翻转。
代码:
public static void main(String[] args) {
//需求:创建一个包含10个随机数的数组,每个随机数的范围是[10, 80],实现数组元素翻转。
//分析:
//1. 创建一个数组。----动态初始化
//2. 创建Random对象
//3. 通过循环为数组赋值,赋随机数,并打印随机数的值。---用于对比数组是否翻转。
//4. 实现数组翻转
// 翻转思路,循环只循环一半,让第一个和最后一个互换,第二个和倒数第二个互换,..
// 互换实现思路,定义一个变量temp,借助中间变量temp实现交换
//5. 打印翻转后的数组数据。
int[] array = new int[10];
Random random = new Random();
for(int i = 0; i < array.length; i++) {
array[i] = random.nextInt(80 - 10 + 1) + 10;
System.out.print(array[i] + " ");
}
System.out.println();
//实现翻转 ? ?
for(int i = 0; i < array.length / 2; i++) {
int temp = 0;
temp = array[i];
array[i] = array[array.length - 1 - i];
array[array.length - 1 - i] = temp;
}
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
?
数组插入数据:指的是向数组中某个位置插入数据,因为数组长度不可变,因此需要保证数组足够长,能容纳下所有的数据。
需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。将66插入到下标为1的位置。
代码:
public static void main(String[] args) {
//需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。
//将66插入到下标为1的位置。
//分析:
//1. 创建一个能容纳10个元素的数组。数组的前七个数是35,22,17,41,72,29,10。
//2. 将数据后移,空出位置来插入数据
// 即: array[7] = array[6];
// array[6] = array[5];
// array[5] = array[4];
// array[4] = array[3];
// array[3] = array[2];
// array[2] = array[1];
// 上述过程可以使用循环实现
//3. 将数据66赋值给array[1]
int[] array = {35, 22, 17, 41, 72, 29, 10, 0, 0, 0};
for(int i = 6; i >= 1; i--) {
array[i+1] = array[i];
}
array[1] = 66;
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
数组删除数据:指的是删除某个下标的数据(或者删除某个指定的数据)。指定的数据被删除后,它后面的数据要前移。
需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。将数组下标为6的数据删除。
代码:
public static void main(String[] args) {
//需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。将数组下标为1的数据删除。
//分析:
//1. 创建一个包含10个元素的数组,数组的前7个数组是35,22,17,41,72,29,10。
//2. 将数据前移,依次覆盖数据。
// 即: array[1] = array[2];
// array[2] = array[3];
// array[3] = array[4];
// array[4] = array[5];
// array[5] = array[6];
// 上面的步骤可以用循环实现
//3. 将array[6]的值改为0
int[] array = {35, 22, 17, 41, 72, 29, 10, 0, 0, 0};
for(int i = 1; i < 6; i++) {
array[i] = array[i + 1];
}
array[6] = 0;
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。删除数组中的数据22。-----提示:先找到数据22的下标,再按下标去删除数据。
代码:
public static void main(String[] args) {
//需求:创建一个容量为10的数组,数组前7个数分别是35,22,17,41,72,29,10。删除数组中的数据22。
//-----提示:先找到数据22的下标,再按下标去删除数据。
//分析:
//1. 创建一个包含10个元素的数组,数组的前7个数组是35,22,17,41,72,29,10。
//2. 定义一个变量保存数据22的下标。
//3. 找到值为22的元素的下标。----数据的查找。
//4. 数据前移
//5. 将最后一个有效数据的值改位0
int[] array = {35, 22, 17, 41, 72, 29, 10, 0, 0, 0};
int index = 0;
for(int i = 0; i < array.length; i++) {
if(array[i] == 22) {
index = i;
break;
}
}
for(int i = index; i < 6; i++) {
array[i] = array[i + 1];
}
array[6] = 0;
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
数组排序指的是让一堆杂乱无章的数据,按从小到大排列,或者按从大到小排列,让其有规律。这个过程就是数组排序。排序的算法很多,例如:冒泡排序,选择排序,快速排序,归并排序,插入排序等等。咱们讲一下冒泡排序和选择排序。
冒泡排序:海底的气泡由于水压的作用,越深的地方气泡就越小,气泡在上浮的过程中,由于水压的减小,气泡会越来越大,到达海面的时候,气泡会最大。基于这个启发,数学家们发明了冒泡排序。
冒泡排序的思想:以从小到大排序为例。依次比较相邻的2个数据,如果前面的数据大于后面的数据,二者交换位置,一趟下来之后,最大的数据就跑到了末尾,这个数据在下一趟不再参与比较。第二趟仍然是依次比较相邻的2个数据,如果前面的数据大于后面的数据,二者交换位置,第二趟下来之后,第2大的数据就跑到了倒数第二位,同样这个数据不再参与下一趟的比较,以此类推,对于具有n个数的数组而言,进行n-1趟上述过程,就能让数组有序。
需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
代码:
public static void main(String[] args) {
//需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
//分析:
//1.创建一个数组保存上述数据
//2.使用冒泡法进行排序
//原始数据 67 42 88 16 25 3------一共6个数据,共比较5趟
//第1趟,一共比较5次
// 第1次 42 67 88 16 25 3
// 第2次 42 67 88 16 25 3
// 第3次 42 67 16 88 25 3
// 第4次 42 67 16 25 88 3
// 第5次 42 67 16 25 3 88-----88不再参与下一轮比较。第1趟找出了最大值
//第2趟,一共比较4次
// 第1次 42 67 16 25 3 88
// 第2次 42 16 67 25 3 88
// 第3次 42 16 25 67 3 88
// 第4次 42 16 25 3 67 88-----67和88不再参与下一轮比较,第2趟找出了第2大值。
//第3趟,一共比较3次
// 第1次 16 42 25 3 67 88
// 第2次 16 25 42 3 67 88
// 第3次 16 25 3 42 67 88-----42,67,88不再参与下一轮比较,第3趟找出了第3大值
//第4趟,一共比较2次
// 第1次 16 25 3 42 67 88
// 第2次 16 3 25 42 67 88-----25,42,67,88不再参与下一轮比较,第4趟找出了第4大值
//第5趟,一共比较1次
// 第1次 3 16 25 42 67 88-----全部数据有序。
int[] array = {67, 42, 88, 16, 25, 3};
for(int i = 0; i < array.length - 1; i++) {
for(int j = 0; j < array.length - 1 - i; j++) {
if(array[j] > array[j + 1]) {
int temp = array[j];
array[j] = array[j + 1];
array[j + 1] = temp;
}
}
}
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
冒泡排序的格式也很固定:
for(int i = 0; i < 数组名.length - 1; i++){
for(int j = 0; j < 数组名.length - 1 - i; j++){
if(数组名[j] > 数组名[j+1]){
数据类型 temp = 数组名[j];
数组名[j] = 数组名[j+1];
数组名[j+1] = temp;
}
}
}
选择排序思想:以从小到大排序为例。第一趟,从数组中找出最小值,并记录最小值的下标,让最小值与数组下标为0的元素交换位置。第二趟,刨除数组下标为0的元素,在剩下的元素中找出最小值,并记录最小值的下标,与数组下标为1的元素交换位置。第三趟,刨除数组下标为0和1的元素,在剩下的元素中找出最小值,并记录最小值的下标,与数组下标为2的元素交换位置,以此类推,如果要对n个数排序,n-1趟即可让数组有序。
需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
代码:
public static void main(String[] args) {
//需求:有如下一组数{67, 42, 88, 16, 25, 3},对其按从小到大的顺序排列。
//分析:
//1.创建一个数组保存上述数据
//2.定义变量index保存最小值的下标。
//3.使用选择排序法进行排序
//原始数据 67 42 88 16 25 3------一共6个数据,共比较5趟
//第1趟,一共比较5次 假定下标为0的元素是最小值。即index初始值是0
// 第1次 67 42 88 16 25 3 下标为1的和下标为index的比较,下标为1的更小,将index更新为1
// 第2次 67 42 88 16 25 3 下标为2的和下标为index的比较,下标为index比较小,不更新index
// 第3次 67 42 88 16 25 3 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第4次 67 42 88 16 25 3 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第5次 67 42 88 16 25 3 下标为5的和下标为index的比较,下标为5的更小,将index更新为5
// 第1趟结束后,最小的元素已经找到,即下标为5的元素,让下标为5的元素和下标为0的元素交换位置。
// 3 42 88 16 25 67---最小值就找出来了。最小值不再参与下一趟比较。
//第2趟,一共比较4次 假定下标为1的元素是最小值。即index初始值是1
// 第1次 3 42 88 16 25 67 下标为2的和下标为index的比较,下标为index比较小,不更新index
// 第2次 3 42 88 16 25 67 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第3次 3 42 88 16 25 67 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第4次 3 42 88 16 25 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第2趟结束后,第二小的元素已经找到,即下标为3的元素,让下标为3的元素和下标为1的元素交换位置。
// 3 16 88 42 25 67---最小值和次小值就找出来了。二者不再参与下一趟比较。
//第3趟,一共比较3次 假定下标为2的元素是最小值。即index初始值是2
// 第1次 3 16 88 42 25 67 下标为3的和下标为index的比较,下标为3的更小,将index更新为3
// 第2次 3 16 88 42 25 67 下标为4的和下标为index的比较,下标为4的更小,将index更新为4
// 第3次 3 16 88 42 25 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第3趟结束后,第三小的元素已经找到,即下标为4的元素,让下标为4的元素和下标为2的元素交换位置。
// 3 16 25 42 88 67---最小的3个数就找出来了。三者不再参与下一趟比较。
//第4趟,一共比较2次 假定下标为3的元素是最小值。即index初始值是3
// 第1次 3 16 25 42 88 67 下标为4的和下标为index的比较,下标为index比较小,不更新index
// 第2次 3 16 25 42 88 67 下标为5的和下标为index的比较,下标为index比较小,不更新index
// 第4趟结束后,第四小的元素已经找到,即下标为3的元素,让下标为3的元素和下标为3的元素交换位置。
// 3 16 25 42 88 67---最小的4个数就找出来了。四者不再参与下一趟比较。
//第5趟,一共比较1次 假定下标为4的元素是最小值。即index初始值是4
// 第1次 3 16 25 42 88 67 下标为5的和下标为index的比较,下标为5的更小,将index更新为5
// 第5趟结束后,第五小的元素已经找到,即下标为5的元素,让下标为5的元素和下标为4的元素交换位置。
// 3 16 25 42 67 88---至此,数据全部有序。
int[] array = {67, 42, 88, 16, 25, 3};
for(int i = 0; i < array.length - 1; i++) {
int index = i;
for(int j = i + 1; j < array.length; j++) {
if(array[j] < array[index]) {
index = j;
}
}
int temp = array[index];
array[index] = array[i];
array[i] = temp;
}
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
选择排序的写法很固定:
for(int i = 0; i < 数组名.length - 1; i++){
int index = i;
for(int j = i + 1; j < 数组名.length; j++){
if(数组名[j] < 数组名[index]){
index = j;
}
}
if(index != i){
数据类型 temp = 数组名[i];
数组名[i] = 数组名[index];
数组名[index] = temp;
}
}
需求:创建一个包含10个随机数的数组,随机数的取值范围是[10, 90],对其按从小到大的顺序排列。
代码:
public static void main(String[] args) {
//需求:创建一个包含10个随机数的数组,随机数的取值范围是[10, 90],对其按从小到大的顺序排列。
//分析:
//1. 创建一个数组,用于保存数据。
//2. 创建Random对象
//3. 通过循环为 数组元素赋值随机数
//4. 使用冒泡法或者选择排序 对数组进行排序
//5. 打印排序后的结果
int[] array = new int[10];
Random random = new Random();
for(int i = 0; i < array.length; i++) {
array[i] = random.nextInt(90 - 10 + 1) + 10;
System.out.print(array[i] + " ");
}
System.out.println();
//冒泡法排序
// for(int i = 0; i < array.length - 1; i++) {
// for(int j = 0; j < array.length - 1 - i; j++) {
// if(array[j] > array[j+1]) {
// int temp = array[j];
// array[j] = array[j+1];
// array[j+1] = temp;
// }
// }
// }
//选择排序
for(int i = 0; i < array.length - 1; i++) {
int index = i;
for(int j = i + 1; j < array.length; j++) {
if(array[j] < array[index]) {
index = j;
}
}
int temp = array[i];
array[i] = array[index];
array[index] = temp;
}
System.out.println("排序后:");
//打印排序后的数组
for(int i = 0; i < array.length; i++) {
System.out.print(array[i] + " ");
}
System.out.println();
}
数组是一个容器,可以存放数据。不仅可以存放基本数据类型,还可以存放引用类型,即数组的元素可以是数组。如果一个数组的元素是数组,这样就构成了一个二维数组。
数组存放普通数据:
数组存放数组:
二维数组的定义格式和一维数组的定义类似,分为2种:推荐使用格式一
格式一:数据类型 [] [] 数组名
示例:int [] [] arr
含义:定义了一个整型的二维数组,数组名是arr。
格式二:数据类型 数组名[] []
示例: int arr[] []
含义:定义了一个整型的二维数组,数组名是arr。
二维数组的初始化也分为:动态初始化 和 静态初始化
动态初始化格式:
数据类型[] [] 数组名 = new 数据类型[第一维元素个数] [第二维元素个数];
示例:int[] [] arr = new int[4] [3];
含义:定义了一个4行3列的二维数组,数组中每个元素的初始值是0。
静态初始化格式:
数据类型[] [] 数组名 = new 数据类型[] []{ {值1,值2,值3..} ,{值1,值2,值3..} ,..};
示例:int[] [] arr = new int[] [] {{8, 22, 35, 17},{13, 9, 26, 21}};
含义:定义了一个2行4列的二维数组,数组的初始值是:8, 22, 35, 17, 13, 9, 26, 21
静态初始化的简化格式:
数据类型[] [] 数组名 = { {值1,值2,值3..} ,{值1,值2,值3..} ,..};
示例:int[] [] arr = {{8, 22, 35, 17},{13, 9, 26, 21}};
含义:定义了一个2行4列的二维数组,数组的初始值是:8, 22, 35, 17, 13, 9, 26, 21
游戏的地图
游戏里的背包、储物柜
彩票购买软件里,多注彩票的存储
修图软件里图片的像素
...
数组名代表整个二维数组。数组名存储的是整个二维数组的起始地址。
如果打印数组名,将会显示一个地址值。
给数组名赋值,将改变二维数组的指向。
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},{13, 9, 26, 21}};
System.out.println(arr);//二维数组在堆区的起始地址
}
语法格式:数组名[第一维的下标]
由于二维数组可以看成1个元素是数组的一维数组。因此 数组名[第一维的下标] 获取的是内层数组的地址。
如果打印 数组名[第一维的下标] 得到的是一个地址值。
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},{13, 9, 26, 21}};
System.out.println(arr);//二维数组在堆区的起始地址
System.out.println(arr[0]);//二维数组第1行元素在堆区的起始地址
System.out.println(arr[1]);//二维数组第2行元素在堆区的起始地址
}
语法格式: 数组名[第一维的下标] [第二维的下标]
示例: arr[1] [2]
含义:访问的是二维数组第2行第3列的元素。
数组名[第一维的下标] [第二维的下标] 可以看成是一个特殊的变量,因此可以对其进行赋值和取值。
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},
? {13, 9, 26, 21}};
int num = arr[0][1];//将第一行第二列元素22赋值给num
System.out.println(num);
arr[1][1] = 100;//把100赋值给第二行第二列的元素。
System.out.println(arr[1][1]);
}
在Java中二维数组本身有一个堆区空间,内部每一个一维数组也有自己独立的堆区空间。二维数组中存储的是每一个一维数组的起始地址。
在C语言中,二维数组所有元素的内存是连续的。
每一维的下标都不能越界。
二维数组的数组名赋值为null的时候,不能再操作数据。
二维数组内的每个一维数组赋值为null的时候,不能再操作数据。
二维数组的遍历指的是找到数组中每个元素。通常使用循环嵌套来遍历数组元素。
数据类型[][] ?数组名 = new 数据类型[第一维元素个数][第二维元素个数];
for(int i = 0; i < 数组名.length; i++){
? ?for(int j = 0; j < 数组名[i].length; j++){
? ? ? ?数组名[i][j] // 数组名[i][j]就是具体的元素。
? }
}
需求:定义一个二维数组{{8, 22, 35, 17}, {13, 9, 26, 21}},遍历数组中的元素。
代码:
public static void main(String[] args) {
int[][] arr = {{8, 22, 35, 17},
? {13, 9, 26, 21}};
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70]。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70]。
//分析:
//1.创建一个3行5列的二维数组
//2.创建Random对象
//3.通过循环为二维数组赋值。
int[][] arr = ?new int[3][5];
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求数组中的最大值。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求数组中的最大值。
//分析:
//1.创建一个3行5列的二维数组
//2.定义一个变量max保存最大值
//3.创建Random对象
//4.通过循环为二维数组赋值。在赋值的过程中,判断元素和max谁大,如果元素大,把元素赋值给max
int[][] arr = ?new int[3][5];
int max = 0;
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
if(arr[i][j] > max) {
max = arr[i][j];
}
}
System.out.println();
}
System.out.println("max = " + max);
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求数组中的最大值以及最大值的下标。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求数组中的最大值以及最大值的下标。
//分析:
//1.创建一个3行5列的二维数组
//2.定义一个变量max保存最大值
//3.创建Random对象
//4.通过循环为二维数组赋值。在赋值的过程中,判断元素和max谁大,如果元素大,把元素赋值给max
//5.遍历二维数组,打印出最大值的下标。
int[][] arr = ?new int[3][5];
int max = 0;
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
if(arr[i][j] > max) {
max = arr[i][j];
}
}
System.out.println();
}
System.out.println("max = " + max);
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
if(arr[i][j] == max) {
System.out.println("i = " + i + ",j = " + j);
}
}
}
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求第2行的平均值。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求第2行的平均值。
//分析:
//1.创建一个3行5列的二维数组
//2.定义一个变量sum保存第2行的和,定义一个变量avg保存平均值
//3.创建Random对象
//4.通过循环为二维数组赋值。
//5.遍历二维数组第2行,对元素求和。
//6.通过sum计算avg
int[][] arr = ?new int[3][5];
int sum = 0;
double avg = 0.0;
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
for(int i = 0; i < arr[1].length; i++) {
sum += arr[1][i];
}
avg = sum * 1.0 / arr[1].length;
System.out.println("sum = " + sum + ",avg = " + avg);
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求第4列的平均值。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],求第4列的平均值。
//分析:
//1.创建一个3行5列的二维数组
//2.定义一个变量sum保存第4列的和,定义一个变量avg保存平均值
//3.创建Random对象
//4.通过循环为二维数组赋值。
//5.遍历二维数组第4列,对元素求和。
//6.通过sum计算avg
int[][] arr = ?new int[3][5];
int sum = 0;
double avg = 0.0;
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
for(int i = 0; i < arr.length; i++) {
sum += arr[i][3];
}
avg = sum * 1.0 / arr.length;
System.out.println("sum = " + sum + ",avg = " + avg);
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],对第3行的数据按从小到大排序。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],对第3行的数据按从小到大排序。
//分析:
//1.创建一个3行5列的二维数组
//2.创建Random对象
//3.通过循环为二维数组赋值。
//4.对第3行数据排序。--冒泡法
//5.遍历二维数组的元素
int[][] arr = ?new int[3][5];
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
System.out.println("-----------");
//冒泡排序
for(int i = 0; i < arr[2].length - 1; i++) {
for(int j = 0; j < arr[2].length - 1 - i; j++) {
if(arr[2][j] > arr[2][j+1]) {
int temp = arr[2][j];
arr[2][j] = arr[2][j+1];
arr[2][j+1] = temp;
}
}
}
//遍历元素
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],对第2列的数据按从小到大排序。
代码:
public static void main(String[] args) {
//需求:创建一个3行5列的二维数组,每个元素的取值范围是[30, 70],对第2列的数据按从小到大排序。
//分析:
//1.创建一个3行5列的二维数组
//2.创建Random对象
//3.通过循环为二维数组赋值。
//4.对第2列数据排序。--冒泡法
//5.遍历二维数组的元素
int[][] arr = ?new int[3][5];
Random random = new Random();
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
arr[i][j] = random.nextInt(70 - 30 + 1) + 30;
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
System.out.println("-----------");
//冒泡排序
for(int i = 0; i < arr.length - 1; i++) {
for(int j = 0; j < arr.length - 1 - i; j++) {
if(arr[j][1] > arr[j+1][1]) {
int temp = arr[j][1];
arr[j][1] = arr[j+1][1];
arr[j+1][1] = temp;
}
}
}
//遍历元素
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
System.out.print(arr[i][j] + " ");
}
System.out.println();
}
}
多维数组指的是三维或者三维以上的数组。Java支持多维数组,数组维数越高,越不容易想象。
上图就是三维数组的一个模型。一维数组是线性的,二维数组是平面,有行和列的概念,三维数组是一个立体,有长宽高的概念。
数据类型[] [] [] 数组名 = new 数据类型[第一维元素个数] [第二维元素个数] [第三维元素个数];
示例:
int[] [] [] arr = new int[3] [4] [3];
含义:定义了一个3层4行3列的数组。即一共3层,每层4行,每行3列。
数组名[下标1] [下标2] [下标3]
示例:
arr[0] [1] [1] = 30;//将第1层,第2行,第2列的值设置为30
int num = arr[0] [1] [1]; //将将第1层,第2行,第2列的值赋值给num
数据类型[][][] 数组名 = new 数据类型[第一维元素个数][第二维元素个数][第三维元素个数];
for(int i = 0; i < 数组名.length; i++){
? ?for(int j = 0; j < 数组名[i].length; j++){
? ? ? ?for(int k = 0; k < 数组名[i][j].length; k++){
? ? ? ? ? ?数组名[i][j][k] //数组名[i][j][k]就是被遍历到的数组元素
? ? ? }
? }
}
需求:创建一个3层3行5列的三维数组,每个元素是[10, 80]之间的随机数,找出数组中的最大值,以及最大值元素的下标。
代码:
public static void main(String[] args) {
//需求:创建一个3层3行5列的三维数组,每个元素是[10, 80]之间的随机数.
//找出数组中的最大值,以及最大值元素的下标。
//分析:
//1.创建一个三维数组
//2.创建Random对象
//3.定义一个变量max保存元素的最大值
//4.通过循环为数组赋值,并求出最大值。
int[][][] arr = new int[3][3][5];
Random random = new Random();
int max = 0;
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
for(int k = 0; k < arr[i][j].length; k++) {
arr[i][j][k] = random.nextInt(80 - 10 + 1) + 10;
System.out.print(arr[i][j][k] + " ");
if(arr[i][j][k] > max) {
max = arr[i][j][k];
}
}
System.out.println();
}
System.out.println();
}
System.out.println("max = " + max);
//找最大值的下标
for(int i = 0; i < arr.length; i++) {
for(int j = 0; j < arr[i].length; j++) {
for(int k = 0; k < arr[i][j].length; k++) {
if(arr[i][j][k] == max) {
System.out.println("i = " + i + ",j = " + j + ",k = " + k);
}
}
}
}
}
?
数据类型 []...[] 数组名 = new 数据类型[第1维元素个数] ...[第n维元素个数];
数组名[下标1]..[下标n]
数据类型[]...[] 数组名 = new 数据类型[第一维元素个数]...[第n维元素个数];
for(int i = 0; i < 数组名.length; i++){
? ?for(int j = 0; j < 数组名[i].length; j++){
? ? ? ...{
? ? ? for(int k = 0; k < 数组名[i][j].length; k++){
? ? ? ? ? 数组名[i]...[k] //数组名[i]...[k]就是被遍历到的数组元素
? ? ? }
? ? ? }
? }
}
数组是一个容器,用于存储数据。数组在创建的时候要确定容量,数组内部的元素类型必须相同。
数组的长度:数组名.length
数组可以动态初始化,也可以静态初始化。
数组的遍历,几维数组就用几层循环嵌套来遍历。
数组通常和循环结合使用。
数组元素的访问:数组名[下标] -----几维数组就要有几个下标。
数组的操作很多,求最值、和、平均值、查找元素、判断是否相等、拷贝、翻转、插入、删除、排序等等。