数组
数组指一组数据的集合,数组中的
每个数据被称作元素
特点
- 数组是一种
引用数据类型
- 长度确定,定义的时候必须指定数组的
长度
。 - 类型确定,定义的时候必须声明数组的
类型
。
数组的初始化
分类
- 一维数组
- 多维数组
一维数组
两种常见的初始化方式:
- 动态初始化(指定长度):在创建数组的时候,直接指定数组当中的数据元素个数。
- 静态初始化(指定内容):在创建数组的时候,不直接指定数据个数多少,而是直接将具体的数据内容进行指定。
动态初始化
动态初始化:创建一个数组,但是没有初始化数组的元素。这种情况需要显式的指定数组大小。
数据类型[ ] 数组名 = new 数据类型[数组长度];
解析含义: 左侧数据类型:也就是数组当中保存的数据,全都是统一的什么类型 左侧的中括号:代表我是一个数组 左侧数组名称:给数组取一个名字 右侧的new:代表创建数组的动作 右侧数据类型:必须和左边的数据类型保持一致 右侧中括号的长度:也就是数组当中,到底可以保存多少个数据,是一个int数字
public class Demo01Array {
public static void main(String[] args) {
// 创建一个数组,里面可以存放300个int数据
// 格式:数据类型[] 数组名称 = new 数据类型[数组长度];
int[] arrayA = new int[300];
// 创建一个数组,能存放10个double类型的数据
double[] arrayB = new double[10];
// 创建一个数组,能存放5个字符串
String[] arrayC = new String[5];
}
}
静态初始化
创建一个数组,并已知数组的内部元素
标准格式:数据类型[] 数组名称 = new 数据类型[] { 元素1, 元素2, ... };
省略格式:数据类型[] 数组名 = {...};
int[] myArr = {0,1,2};
public class ArrayDemo {
public static void main(String[] args) {
/*
* 定义语法1
* 数据类型[ ] 数组名 = new 数据类型[size];
* 定义语法2
* 数据类型[ ] 数组名 = {数据1,数据2,数据3};
**/
int[] myArr = new int[3];
System.out.println(myArr[2]);
int[] myArr1 = {100, 200, 300};
System.out.println(myArr1[1]);
// 数组长度
// 最大索引 = 数组长度 - 1
System.out.println(myArr.length);
System.out.println(myArr1.length);
}
}
注意事项:
1. 静态初始化没有直接指定长度,但是仍然会自动推算得到长度。
2. 静态初始化标准格式可以拆分成为两个步骤。
3. 动态初始化也可以拆分成为两个步骤。
4. 静态初始化一旦使用省略格式,就不能拆分成为两个步骤了。
public class Demo03Array {
public static void main(String[] args) {
// 省略格式的静态初始化
int[] arrayA = { 10, 20, 30 };
// 2.静态初始化的标准格式,可以拆分成为两个步骤
int[] arrayB;
arrayB = new int[] { 11, 21, 31 };
// 3.动态初始化也可以拆分成为两个步骤
int[] arrayC;
arrayC = new int[5];
// 4.静态初始化的省略格式,不能拆分成为两个步骤。
// int[] arrayD;
// arrayD = { 10, 20, 30 };
}
}
使用建议:
- 如果不确定数组当中的具体内容,用动态初始化;否则,已经确定了具体的内容,用静态初始化
数组的默认初始值
数组类型 | 默认初始化 |
---|---|
byte short int long | 0 |
float double | 0.0 |
char | 一个空字符(空格),即‘\\u0000’ |
boolean | false |
引用数据类型 | null ,表示变量不引用任何对象 |
静态初始化其实也有默认值的过程,只不过系统自动马上将默认值替换成为了大括号当中的具体数值
数组的索引
直接打印数组名称,得到的是数组对应的:内存地址哈希值
。
访问数组元素的格式:数组名称[索引值]
【注意】
索引值从
0
开始,一直到“数组的长度-1
”为止 ```java public class Demo01 { public static void main(String[] args) {// 静态初始化的省略格式
int[] array = { 10, 20, 30 };
System.out.println(array); // [I@6e0be858
// 直接打印数组当中的元素
System.out.println(array[0]); // 10
System.out.println(array[1]); // 20
System.out.println(array[2]); // 30
System.out.println("=============");
// 也可以将数组当中的某一个单个元素,赋值交给变量
int num = array[1];
System.out.println(num); // 20
}
}
<a name="dHCaB"></a>
### 内存概述
内存是计算机中的重要原件,临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。 <br />Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
**JVM的内存划分**
| **区域名称** | **作用** |
| --- | --- |
| 方法栈 | 方法运行时使用的内存,比如main方法运行,进入方法栈中执行,存放的都是方法中的`局部变量` |
| <br /><br />堆内存 | 存储对象或者数组,凡是`new`出来的东西,都在堆中<br />- 堆内存的东西都有一个地址值:`16进制`<br />- 堆内存里面的数据都有`默认值`<br /> |
| 方法区 | 存储`.class`相关信息,包含方法的信息 |
| 本地方法栈 | JVM在使用操作系统功能的时候使用 |
| 寄存器 | 与`cpu`相关 |
<a name="HhbWJ"></a>
### 数组在内存中的存储
> <a name="WQNTh"></a>
#### 一个数组内存图
```java
public class Demo02 {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);//[I@6e0be858
}
}
以上方法执行,输出结果[I@6e0be858,是数组在内存中的地址。new出来的内容,都是在堆内存中存储的,而方法中的变量arr保存的是数组的地址。
程序执行流程:
main
方法进入方法栈执行- 创建数组,jvm会在堆内存中开辟空间,存储数组
- 数组在内存中会有自己的内存地址,以16进制数表示
- 数组中有3个元素,默认值0
- jvm将数组的内存地址赋值给引用类型变量arr
- 变量arr保存的是数组内存中的地址,而不是一个具体的数值,因此称为饮用数据类型
两个数组内存图
public class Demo02 {
public static void main(String[] args) {
int[] arr = new int[3];
int[] arr2 = new int[2];
System.out.println(arr);//[I@6e0be858
System.out.println(arr2);//[I@61bbe9ba
}
}
两个引用指向同一个数组的内存图
获取数组长度
格式:数组名称.length
public class ArrayLength {
public static void main(String[] args) {
int[] array = {12,23,43,55,6,7,2,3,3,4,6};
int len = array.length;
System.out.println("array数组的长度是:" + len);
}
数组一旦创建,程序运行期间,长度不可改变,意思是
new
出来的长度不可改变
public class ArrayLength {
public static void main(String[] args) {
int[] array = new int[3];
System.out.println(array.length); // 3
array = new int[5];
System.out.println(array.length); // 5
}
}
以上是变量array被赋值,并不少改变new出来数组长度
数组遍历
public class TestArray03 {
public static void main(String[] args) {
int[] arr = { 1, 2, 3, 4, 5 }; // 定义数组
// 使用for循环遍历数组的元素
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]); // 通过索引访问元素
}
}
}
数组最值
最大值
public class DemoMax {
public static void main(String[] args) {
int[] array = {1,34,56,68,4,32,3};
int max = array[0];//// 比武擂台
for (int i = 1; i < array.length; i++) {
// 如果当前元素,比max更大,则换人
if(array[i]>max){
max = array[i];
}
}
// 谁最后最厉害,就能在max当中留下谁的战斗力
System.out.println("最大值:"+max);
}
}
最小值
public class DemoMin {
public static void main(String[] args) {
int[] array = {1,34,56,68,4,32,3};
int min = array[0];//// 比武擂台
for (int i = 1; i < array.length; i++) {
// 如果当前元素,比min更小,则换人
if(array[i]<min){
min = array[i];
}
}
// 谁最后最厉害,就能在max当中留下谁的战斗力
System.out.println("最大值:"+min);
}
}
数组反转
- 数组的反转: 数组中的元素颠倒顺序,例如原始数组为1,2,3,4,5,反转后的数组为5,4,3,2,1
public class ArrayReverse {
public static void main(String[] args) {
int[] array = {23,45,56,2,35,46};
//遍历数组原来的样子
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);}
/*
初始化语句:int min = 0, max = array.length - 1
条件判断:min < max
步进表达式:min++, max--
循环体:用第三个变量倒手
*/
for (int min =0,max = array.length-1;min<max;min++,max--) {
//利用第三方变量完成数组中的元素交换
int temp = array[min];
array[min] = array[max];
array[max] = temp;
}
// 反转后,遍历数组
for (int i = 0; i < array.length; i++) {
System.out.println(array[i]);
}
}
}
二维数组
语法1
数据类型[][] 数组名 = {{...}, {...}, {...}};
int[][] arr = {{1, 2, 3}, {4, 5, 6}, {7, 8, 9}};
语法2
数据类型[][] 数组名 = 数据类型 [二维数组长度][二维数组中一维数组的长度];
int[][] arr2 = new int[2][2];//{{0,0},{0,0}}
二维数组遍历
public class TestArray15{
public static void main(String[] args){
//定义一个二维数组:
int[][] arr = new int[3][];//本质上定义了一个一维数组,长度为3
int[] a1 = {1,2,3};
arr[0] = a1;
arr[1] = new int[]{4,5,6,7};
arr[2] = new int[]{9,10};
//读取6这个元素:
//System.out.println(arr[1][2]);
//对二维数组遍历:
//方式1:外层普通for循环+内层普通for循环:
for(int i=0;i<arr.length;i++){
for(int j=0;j<arr[i].length;j++){
System.out.print(arr[i][j]+"\t");
}
System.out.println();
}
//方式2:外层普通for循环+内层增强for循环:
for(int i=0;i<arr.length;i++){
for(int num:arr[i]){
System.out.print(num+"\t");
}
System.out.println();
}
//方式3:外层增强for循环+内层增强for循环:
for(int[] a:arr){
for(int num:a){
System.out.print(num+"\t");
}
System.out.println();
}
//方式4:外层增强for循环+内层普通for循环:
for(int[] a:arr){
for(int i=0;i<a.length;i++){
System.out.print(a[i]+"\t");
}
System.out.println();
}
}
}
二维数组求和
int[][] arr2 = { {1,2},{3,4,5},{6,7,8,9,10} };
int sum2 = 0;
for (int i=0; i<arr2.length; i++) {
for (int j=0; j<arr2[i].length; j++) {
//System.out.println(arr2[i][j])
sum2 += arr2[i][j];
}
}
System.out.println("sum2= "+ sum2);
}
}
数组异常
1、**越界异常**
访问数组的元素时,索引不能超出0~length-1这个范围。ArrayIndexOutOfBoundsException
2、**空指针异常**
在使用变量引用一个数组时,变量必须指向一个有效的数组对象,如果该变量的值为null,则意味着没有指向任何数组,此时通过该变量访问数组的元素会出现空指针异常。
数组应用
删除指定位置上的元素
import java.util.Arrays;
public class TestArray08{
public static void main(String[] args){
//功能:给定一个数组,删除下标为2元素
//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,34,45,56,7,666};
// 0 1 2 3 4 5
//2.输出删除前的数组:
System.out.println("删除元素前的数组:"+Arrays.toString(arr));
//3.删除
/*
arr[2] = arr[3];
arr[3] = arr[4];
arr[4] = arr[5];
*/
int index = 0;
for(int i=index;i<=arr.length-2;i++){
arr[i] = arr[i+1];
}
arr[arr.length-1] = 0;
//4.输出删除后的数组:
System.out.println("删除元素后的数组:"+Arrays.toString(arr));
}
}
添加元素
public class TestArray07{
public static void main(String[] args){
//功能:给定一个数组,在数组下标为2的位置上添加一个元素91
//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,55,66,77,88,999,89};
// 0 1 2 3 4 5
//2.输出增加元素前的数组:
System.out.print("增加元素前的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}
//3.增加元素
/*
arr[5] = arr[4];
arr[4] = arr[3];
arr[3] = arr[2];
*/
int index = 1;//在这个指定位置添加 元素
for(int i=arr.length-1;i>=(index+1);i--){
arr[i] = arr[i-1];
}
arr[index] = 666;
//4.输出增加元素后的数组:
System.out.print("\n增加元素后的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}
}
}
将添加功能提取为一个 方法
import java.util.Scanner;
public class TestArray07{
public static void main(String[] args){
//功能:给定一个数组,在数组下标为2的位置上添加一个元素91
//1.给定一个数组:
int[] arr = {12,34,56,7,3,10,55,66,77,88,999,89};
// 0 1 2 3 4 5
//2.输出增加元素前的数组:
/*
System.out.print("增加元素前的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}
*/
//从键盘接收数据:
Scanner sc = new Scanner(System.in);
System.out.println("请录入你要添加元素的指定下标:");
int index = sc.nextInt();
System.out.println("请录入你要添加的元素:");
int ele = sc.nextInt();
//3.增加元素
//调用方法:
insertEle(arr,index,ele);
//4.输出增加元素后的数组:
System.out.print("\n增加元素后的数组:");
for(int i=0;i<arr.length;i++){
if(i!=arr.length-1){
System.out.print(arr[i]+",");
}else{//i==arr.length-1 最后一个元素不用加,
System.out.print(arr[i]);
}
}
}
/*
提取一个添加元素的方法:
在数组的指定位置上添加一个指定的元素。
在哪个数组的哪个位置添加哪个元素!
不确定因素:形参:哪个数组,哪个位置,哪个元素
返回值:无
*/
public static void insertEle(int[] arr,int index,int ele){
for(int i=arr.length-1;i>=(index+1);i--){
arr[i] = arr[i-1];
}
arr[index] = ele;
}
}
数组最值的计算
方法1
public class TestArray03 {
public static void main(String[] args) {
int[] arr = { 4, 1, 6, 3, 9, 8 }; // 定义一个数组
int max = arr[0]; // 定义变量max用于记住最大数,首先假设第一个元素为最大值
// 下面通过一个for循环遍历数组中的元素
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) { // 比较 arr[x]的值是否大于max
max = arr[i]; // 条件成立,将arr[x]的值赋给max
}
}
System.out.println("max=" + max); // 打印最大值
}
}
方法2
public class TestArray04{
public static void main(String[] args){
int[] arr = {12,3,7,4,8,725,9,45,666,36}; //1.给定一个数组
//2.求出数组中的最大值:
//调用方法:
int num = getMaxNum(arr);
System.out.println("当前数组中最大的数为:"+num);
}
/*
想提取一个方法:求数组中的最大值
*/
public static int getMaxNum(int[] arr){
int maxNum = arr[0];
for(int i=0;i<arr.length;i++){
if(arr[i]>maxNum){
maxNum = arr[i];
}
}
return maxNum;
}
}
数组查询
查询指定位置的元素
public class TestArray05{
public static void main(String[] args){
//查询指定位置的元素
//给定一个数组:
int[] arr = {12,34,56,7,3,10};
//查找索引为2的位置上对应的元素是什么?
System.out.println(arr[2]);
}
}
查询元素对应的索引
查询存在的索引
public class TestArray06 {
public static void main(String[] args) {
//找出元素对应的索引
int[] arr = {12,34,56,7,3,56};
//查询元素56对应的索引
int index = 0;
for (int i = 0; i < arr.length; i++) {
if(arr[i]==56){
index = i;//只要找到了元素,index就变成i
break; // 只要找到这个元素,循环就停止
}
}
System.out.println("元素对应的索引:"+index);//2
}
}
查询不存在的索引
出现问题
public class TestArray06 {
public static void main(String[] args) {
//找出元素对应的索引
int[] arr = {12,34,56,7,3,56};
//查询元素56对应的索引
int index = 0;
for (int i = 0; i < arr.length; i++) {
if(arr[i]==900){
index = i;//只要找到了元素,index就变成i
break; // 只要找到这个元素,循环就停止
}
}
System.out.println("元素对应的索引:"+index);//0
}
}
优化
public class TestArray06 {
public static void main(String[] args) {
//找出元素对应的索引
int[] arr = {12,34,56,7,3,56};
//查询元素56对应的索引
int index = -1;//初始值不是数组的索引即可
for (int i = 0; i < arr.length; i++) {
if(arr[i]==900){
index = i;//只要找到了元素,index就变成i
break; // 只要找到这个元素,循环就停止
}
}
if(index!=-1){
System.out.println("元素对应的索引:"+index);
} else{
System.out.println("查无次数");
}
}
}
将查指定元素对应的索引的功能提取为方法
public class TestArray06{
public static void main(String[] args){
int[] arr = {12,34,56,7,3,56}; //给定一个数组
//调用方法:
int index = getIndex(arr,999);//后续对index的值进行判断:
if(index!=-1){
System.out.println("元素对应的索引:"+index);
}else{//index==-1
System.out.println("查无次数!");
}
}
/*
定义一个方法:查询数组中指定的元素对应的索引
不确定因素:哪个数组,哪个指定元素 (形参)
返回值:索引
*/
public static int getIndex(int[] arr,int ele){
int index = -1; //这个初始值只要不是数组的索引即可
for(int i=0;i<arr.length;i++){
if(arr[i]==ele){
index = i;//只要找到了元素,那么index就变成为i
break;//只要找到这个元素,循环就停止
}
}
return index;
}
}
数组_可变参数
定义
1、使用...
表示可变长参数
print(String... args){
...}
2、在具有可变长参数的方法中可以把参数当成数组使用,例如可以循环输出所有的参数值
print(String... args){
for(String temp:args)
System.out.println(temp);
}
可变参数作用
提供了一个方法,参数的个数是可变的 ,解决了部分方法的重载问题
可变长参数的方法的调用
调用的时候可以给出任意多个参数也可不给参数
print();
print("hello");
print("hello","lisi");
print("hello","张三", "alexia")
注:可变参数和其他数据一起作为形参的时候,可变参数一定要放在最后
public class TestArray12{
public static void main(String[] args){
//method01(10);
//method01();
//method01(20,30,40);
method01(30,40,50,60,70);
//method01(new int[]{11,22,33,44});
}
public static void method01(int num2,int...num){
System.out.println("-----1");
for(int i:num){
System.out.print(i+"\t");
}
System.out.println();
System.out.println(num2);
}
}