数组定义和访问
容器的概念
容器:就是将多个数据存储到一起,每个数据称为该容器的元素。
生活中的容器:水杯,excle
数组概念
数组概念:就是存储数据长度固定的容器,要保证每个数据的数据类型要一致。
数组的定义:
方式一:
格式:
数组存储的数据类型[] 数组名称 = new 数组存储的数据类型[长度]; //(长度是>=0的正整数)
解析:
- 数组存储的数据类型:决定了该容器能够存储什么样的数据
- []:表示数组
- 数组名称:给定义数组起一个变量名字,要满足标识符的命名规范
- new:关键字,创建数组使用的关键字。
- 数组存储的数据类型:决定了该容器能够存储什么样的数据
- [长度]:数组的长度,表示数组中能够存储多少个元素
备注:数组一但创建,长度不能发生改变,数组具备一个定长特性。
方式二:
格式:
数组的数据类型[] 数组名称 = new 数组的数据类型[]{元素1,元素2,元素3,..........};
方式三:
格式:
数组的数据类型[] 数组名称 = {元素1,元素2,元素3.........};
数组的特点:
- 数组的长度在程序的运行期间不能改变。
- 数组本身就是一种引用数据类型
- 数组定义时是引用类型,但是数组容器里面存储的元素可以是基本数据类型也可以是引用数据类型。
- 数组当中存储的多个数据,类型保持一致
数组初始化:
相当于在内存当中创建了一个数组,并且向数组容器中赋予一些默认值
默认值:
对于int 整数类型来说,默认值是0;
对于浮点型类型来说,默认值是0.0;
对于字符类型来说,默认值是"\u0000"; 显现的是一个空格
对于布尔类型来说,默认值是false;
对于引用类型来说,默认值是null;
两种常见的初始化动作
-
静态初始化(指定内容):在创建数组的时候,一般不指定数组的长度(存储元素的个数),而是直接指定具体的内容。
int[] ages = {18,19,20,21};
-
动态初始化(指定长度即可):在创建数组的时候直接指定数组的长度(存储元素的个数)。
int[] scores = new int[41];//相当于在内存中存储了41个0 int[] scores;//定义声明 scores = new int[41];
备注:静态初始化虽然没有直接指定长度,但程序会推算得到的该数组的长度
建议:
如果不确定数组当中存储的内容,用动态初始化,反之内容已经确定了使用静态初始化。
大多数情况下建议使用动态初始化。
数组的访问
索引: 角标,下标
每一个存储到数组当中的元素,都会自动分配一个编号,从0开始,这个系统自动分配的编号称为数组的索引(index),可以通过索引访问数组当中的元素。
格式
数组名称[索引]
数组的长度属性
每个数组都有长度,而且是固定的,Java会自动赋给数组一个属性,可以获取到数组的长度属性。
格式
数组名称.length
属性length代表数组的长度,int类型,数组的最大索引值为数组名.length-1
索引访问数组当中的元素操作
- 修改数组当中索引对应位置上的值:数组名[索引] = 数值;
- 变量 = 数组名称[索引],从数组当中取出一个值,赋给一个变量
数组原理内存图解
内存
内存是计算机中一个很重要的原件,是一个临时存储区域,作用是当程序运行过程中,我们编写的代码文件存放在硬盘当中,硬盘当中的程序文件不会运行,存放到内存当中,当程序运行完毕后程序会清空内存
Java虚拟机当中的内存划分
为了提高运行效率,就对内存空间进行不同区域的划分,每一片区域都有特定的处理方式和内存管理方式
JVM内存划分
区域名称 | 作用 |
---|---|
寄存器 | 给cpu使用,和我们的开发没有关系 |
本地方法栈 | JVM虚拟机在使用操作系统功能时使用的,和我们的开发没有关系 |
方法区 | 存储可以运行的class文件(常量池,静态域) |
方法栈(stack) | 方法运行时使用的内存,比如说main方法运行,进入方法栈中运行 |
堆内存(heap) | 存储对象或者数组,new出来的对象,都存储在堆内存当中 |
数组在内存当中的存储
一个数组的内存存储
public static void main(String[] args){
int[] arr = new int[3];
System.out.println(arr);//内存地址哈希值
}
程序执行流程:
- main方法进入方法栈中执行
- 创建数组,JVM在堆内存开辟空间,存储数组
- 数组的会在内存当中有自己的内存地址,以十六进制表示
- 数组当中有三个元素,默认值位0
- JVM将数组的内存地址赋值给应用类型变量arr
- 变量arr保存的数组是在内存当中的地址值,而不是一个具体的数值
两个数组的内存分析图解
public static void main(String[] args){
int[] arr = new int[3];
int[] arr2 = new int[2];
System.out.println(arr);//内存地址哈希值
System.out.println(arr2);
}
两个变量指向同一个数组的时候
public static void main(String[] args){
//定义一个数组,动态初始化
int[] arr = new int[3];//0 0 0
//通过索引访问数组当中的元素
arr[0] = 10;
arr[1] = 20;
arr[2] = 30;
//查看arr第二个元素
System.out.println(arr[1]);
//定义一个数组,将上一个数组赋值给该数组
int[] arr2 = arr;
arr2[1] = 50;
//查看arr中的第二个元素
System.out.println(arr[1]);
}
原理分析图解
数组的常见错误操作
数组的越界异常操作
public static void main(String[] args){
//动态初始化一个数组
int[] arr = new int[];
//访问索引位5的
System.out.println(arr[5]);
}
数组索引是从0开始,最大索引值时 arr.length-1 [0, arr.length-1]
如果访问数组元素是,索引不在该区间中,程序就会抛出数组索引越界异常。
在开发中不要出现索引越界异常现象,会导致程序异常终止。
空指针异常
public static void main(String[] args){
//动态初始化一个数组
int[] arr = new int[3];
arr = null;
//查看arr数组的第三个元素
System.out.println(arr[2]);
}
数组空指针异常,就是在程序运行过程中,有一个在内存当中不存在的一个变量被引用到了
数组遍历【重点】
数组遍历:就是将数组当中的每一个元素获取出来,就是遍历。遍历是我们的操作数组的核心和重点内容
public static void main(String[] args){
//静态初始化一个数组
int[] arr = {1,2,3,4};
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[3]);
}
数组的索引从0开始依次递增,递增到arr.length-1为止,引入循环
public static void main(String[] args){
//静态初始化一个数组
int[] arr = {1,2,3,4};
//数组遍历 for或者while循环
for (int i = 0; i <= arr.length-1; i++){//遍历容器的时候,初始化语句中的变量一般代表索引值
System.out.println(arr[i]);
}
}
数组当中的最大值
最大值:从数组的所有元素中找出最大值
思路:
- 定义一个最大值变量,保存数组当中的第一个元素(数组当中索引值为0)
- 遍历数组,获取数组当中的每一个元素
- 将遍历到的元素和最大值变量进行比较
- 如果数组元素的值大于最大值变量,就把数组元素给最大值变量
- 数组遍历结束,最大值变量保存的就是数组当中的最大值
public static void main(String[] args){
//静态初始化数组容器
int[] arr = {3000,200,1000,10000,5000};
//定义一个最大值变量,保存数组当中第一个元素
int max = arr[0];
for (int i = 1; i <= arr.length-1; i++){
//将遍历到的的元素和保存的最大值进行比较
if (arr[i] > max){
max = arr[i];
}
}
//数组遍历结束,最大值变量保存的就是数组当中的最大值
System.out.println("最大值:" + max);
}
数组的反转
数组的反转:数组中的元素颠倒顺序,例如:原始数组为1,2,3,4,5 数组反转之后为5,4,3,2,1;
思路:本质是考察如何交换两个变量的值 两种方式
- 实现反转,就需要将数组最远端和最近端元素位置互换
- 定义两个变量,保存数组的最小索引和最大索引
- 让两个索引上的元素交换位置
- 最小的索引变量++,最大的索引变量–,再次交换位置
- 直到 最小的索引 >= 最大索引 时停止
准备一个需要反转的数组 int[] arr = {1,2,3,4,5,6};
定义两个索引变量,一个索引变量指向最小索引,一个指向最大索引
int min = 0;
int max = arr.length-1;
遍历数组让两个索引的变量产生变化
min++;
max--;
条件 min < max
交换最小索引元素和最大索引元素;需要定义第三方变量
int temp = 0;
temp = arr[min];//把最小的索引元素赋值给第三方变量
arr[min] = arr[max];//把最大的索引元素赋值给最小的索引元素
arr[max] = temp;//把第三方变量的值赋值给最大索引的元素
//第一种思路
public static void main(String[] args){
int[] arr = {1,2,3,4,5};
//遍历数组 for
for( int min = 0, int max = arr.length-1; min < max; min++,max--){
int temp = 0;
temp = arr[min];
arr[min] = arr[max];
arr[max] = temp;
}
//遍历查看反转之后的数组内容
for (int i = 0; i < arr.length; i++){
System.out.println(arr[i]);
}
//第二种思路:
int[] arr = {1,2,3,4,5};
/*定义一个最小索引变量i
最大索引为arr.length-1-i;
当i= 0的时候
最小索引0
最大索引arr.length-1-0
当i = 1的时候
最小索引 1
最大索引arr.length-1-1
...
i < arr.length/2 结束
*/
//遍历数组
for (int i = 0; i < arr.length/2; i++){
//交换变量
int temp = 0;
temp = arr[i];
arr[i] = arr[arr.length-1-i];
arr[arr.length-1-i] = temp;
}
}
二维数组
定义方式:和一维数组是一样的也有三种方式
方式一:
数组的数据类型[][] 数组名称 = new 数组的数据类型[长度1][长度2];
长度1 不可省略,代表该二维数组里面存储的元素个数
长度2 可以省略,代表该二维数组里面的元素(数组里面的元素个数),而且它里面的数组的元素个数一样
如: int[][] arr = int[3][2];
长度3-->该arr数组里面有三个元素(数组)
长度2-->该arr数组里面的每个数组元素都有两个元素
相当于---> int[][] arr = {{0,0},{0,0},{0,0}};
方式二:
数组的数据类型[][] 数组名称 = new 数组的数据类型[][]{{元素1,元素2,...},{元素1,元素2,元素3,...},{....},....};
方式三:
数组的数据类型[][] 数组名称 = {{元素1,元素2,...},{元素1,元素2,元素3,...},{....},....};
二维数组元素访问方式
借助于索引
格式:
数组名称[索引]--->访问的是二维数组当中的一维数组元素
//访问二维数组当中的以为数组里面的元素
数组名称[一维数组的索引值][一维数组里面的元素索引值]
如: int[][] arr = {{10,20,30},{40,50\''},{70,80,100}};
//访问arr数组中的10元素
arr[0][0] = 10;
//访问80
arr[2][1] = 80;
arr.length//二维数组中一维数组的个数
arr[i].lenght//二维数组中第i个一维数组中元素的个数