这篇文章,我们来讲一下java中的数组。数组是java中很重要很基础的一个东西,大家要注意。
目录
1.数组的介绍
什么是数组?
数组指的是一种容器,可以用来存储同种数据类型的多个值
注意:
数组在存储数据时,可以结合自动类型转换来思考
例如:
int 类型的数组,可以存byte类型,short类型 int 类型,不能存boolean类型,double类型
建议:
我们定义数组的类型和里面存储数据的类型要保持一致
2.数组的定义和静态初始化
下面,我们来看一下数组的定义和初始化
2.1 数组的定义
在讲数组的定义之前,我们先来看一下变量的定义:
int num = 100;
等号左边是定义,等号右边是赋值 。我们这里讲的数组的定义就是将等号左边的那部分
数组的定义方式:
方式一:数据类型 [ ] 数组名
int[] arr;
方式二:数据类型 数组名 [ ]
int brr[];
解释:以方式一为例来解释一下
前面的数据类型,表明了这个数组中应该存什么样的数据;中间的 [ ] 表明这是一个数组;后面的数组名,是给这个数组命名,方便以后的使用;其中数组名和 [ ] 的位置不做要求,但是我们通常习惯使用第一种。
2.2 数组的静态初始化
初始化:就是在内存中,为数组容器开辟空间,并将数据存入到容器中的过程
这里我先讲一下数组的静态初始化
完整格式:数据类型 [ ] 数组名 = new 数据类型 [ ] {元素1,元素2,元素3……}
范例:
int[] arr = new int[]{1,2,3,4,5,6};
简化格式: 数据类型 [ ] 数组名 = {元素1,元素2,元素3……}
范例:
double[] arr1 = {1.1,2.2,3.3,4.4};
注意:数组一旦创建完成,内存就会根据代码给数组开辟内存空间,其长度不能改变。即数组一旦创建,其长度不能改变
3.数组的地址值和元素访问
下面,我们来介绍一下数组的地址值和元素访问
3.1数组的地址值
首先,我们来可以先代码:
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6};
System.out.println(arr);
}
然后看一下结果:
解释:
我们定义一个数组,就是在内存中开辟一块空间,然后在这个空间里面放上数组里面的元素。数组的地址值就是数组在内存中的位置,再说具体点,就是数组中的首元素在内存中的位置 。
扩展:地址值的含义
下面来解释一下地址值的含义:[i@1b6a3586
[ :表示当前是一个数组(就是数组 [ ] 的缩写)
i :表示当前数组中的元素都是 int 类型的(是 int 的缩写)
@:间隔符号(是固定格式)
1b6a3586:这才是数组真正的地址(是十六进制数)
但是,我们平时习惯把这个整体叫做数组的地址值
3.2数组的元素访问
下面,我们来看一下数组元素的访问
数组元素的访问格式:数组名 [ 索引 ];
索引:也叫做下标,角标;就是数组容器中每个小格子的编号(计算机中是从0开始的)
索引特点:从0开始,逐个+1,连续不间断
下面看一个代码:
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6};
arr[0] = 100;
System.out.println(arr[0]);// 100
}
注意:数组中的元素一旦被覆盖,原来的元素就不存在了
4.数组遍历
下面,我们来看一下数组的遍历
数组遍历:将数组中的所有内容取出来,取出来之后可以(打印,求和,判断……)
注意:遍历指的是取出数据的整个过程,不要局限的理解为;遍历就是打印
下面看一下代码演示:
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6};
//遍历方式1:逐个打印
// 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]);
// System.out.println(arr[5]);
//遍历方式2:利用循环
// for (int i = 0; i < 6; i++) {
// System.out.println(arr[i]);
// }
//拓展:获取数组长度的属性:length
//用法:数组名.length
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
看下结果:
5.数组动态初始化
下面,我们来看一下数组的动态初始化
动态初始化:初始化时只指定数组长度,由系统为数组分配初始值
格式:数组类型 [ ] 数组名 = new 数组类型 [ 数组长度 ]
范例:
int[] arr = new int[5];
数组的默认初始化值:
- 整数类型:默认初始化值为:0
- 小数类型:默认初始化值为:0.0
- 字符类型:默认初始化值为:'/u0000',打印出来就是空格
- 布尔类型:默认初始化值为:false
- 引用数据类型:默认初始化值为:null(引用数据类型:可以将除了那4类8种外的所有类型都认为是引用数据类型)
5.1静态初始化与动态初始化的区别
静态初始化:手动指定数组元素,系统会根据元素个数,计算出数组长度
适用场景:需求中已经明确了要操作的具体数据,直接静态初始化即可
动态初始化:手动指定数组长度,由系统给出默认初始化值
适用场景:只明确元素个数,不明确具体数值,推荐使用动态初始化
6.数组常见问题
数组的常见问题:索引越界
索引越界:当访问数组中不存在的索引,就会引起索引越界异常
下面来看一下具体的代码:
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
System.out.println(arr[6]);
}
看下结果:
分析:
Exception:异常,就是代码出现问题
在方法“main”中出现异常,后面是异常的名字:java.lang.ArrayIndexOutOfBoundsException,明确的出错点:6
在 包Day0320的ArrayDemo1类的方法main中的第25行
以上就是报错信息的解读,大家要学会读报错信息
7.数组常见操作
下面就是来做一些小练习
7.1 求最值
需求:已知数组元素为{11,54,63,2,45,78},求其中的最大值
代码如下:
public class ArrayDemo2 {
public static void main(String[] args) {
int[] arr = new int[]{11,54,63,2,45,78};
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (max < arr[i])
max = arr[i];
}
System.out.println("最大值为:"+max);
}
}
结果如下:
7.2遍历数组求和
需求:生成10个0~100之间的随机数存入数组,然后求出所有数据的和,并求出所有数据的平均数,然后求出有多少数据比平均值小
下面看一下代码:
public class ArrayDemo2 {
public static void main(String[] args) {
//题目简单,就不写注释了
int[] arr = new int[10];
Random random = new Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(100);
}
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum = sum + arr[i];
}
System.out.println("数组所有元素的和为:"+sum);
double avg = sum/arr.length;
System.out.println("数组的平均数为:"+avg);
int num = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i]<avg)
num++;
}
System.out.println("共有"+num+"个数小于平均数");
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i]+" ");
}
}
}
看下结果:
7.3交换数组中的数据
需求:定义一个数组,存入1,2,3,4,5,下面要求将该数组整体往前移动2位
移动前:1,2,3,4,5
移动后:3,4,5,1,2
代码如下:
public class ArrayDemo3 {
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5,6};
Scanner scanner = new Scanner(System.in);
System.out.print("请输入往前移动的位数:");
int m = scanner.nextInt();
for (int i = 0; i < m; i++) {
int temp = arr[0];
for (int k = 0; k < arr.length-1 ; k++) {
arr[k] = arr[k+1];
}
arr[arr.length-1] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
}
}
结果如下:
详细的解题思想和其他的解法我会在算法的博客中写,这里只是简单的看一下
7.4 打乱数组中的顺序
需求:定义一个数组,存入1~5,要求打乱数组中所有数据的顺序
代码如下:
public static void main(String[] args) {
int[] arr = new int[]{1,2,3,4,5};
Random random = new Random();
int randomIndex = random.nextInt(arr.length);
for (int i = 0; i < arr.length; i++) {
int temp = arr[i];
arr[i] = arr[randomIndex];
arr[randomIndex] = temp;
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
结果:
8.数组的内存
下面我们来讲一下数组的内存图
8.1 java的内存分配
我们知道,每一款软件在运行时,计算机都会为其分配内存空间。我们的程序在运行时,计算机也会为JVM分配内存空间的。
为了更好的管理内存,JVM将内存分为5部分
- 栈:方法运行时使用的内存,比如main方法运行,进入方法栈中执行
- 堆:存储对象或者数组,new来创建的,都存储在堆内存中
- 方法区:存储可以运行的class文件(jdk7以前,方法区和堆是放在一起的)
- 本地方法栈:JVM在使用操作系统功能的时候使用,和我们开发无关
- 寄存器:给CPU使用,和开发无关
下面看一下最简单的代码的内存图:
代码如下:
public static void main(String[] args) {
int a = 10;
int b = 20;
int c = a + b;
System.out.println(c);
}
内存图如下:
8.2 数组的内存概述
下面,我们还是根据代码来分析数组的内存
代码如下:
public static void main(String[] args) {
int[] arr = new int[2];
System.out.println(arr);
System.out.println(arr[0]);
arr[1] = 10;
System.out.println(arr[1]);
}
内存图如下:
解析:
首先,我们在main方法中创建一个数组,java就会在堆中开辟一块空间,把这块空间的首地址赋给arr,所以我们打印输出 arr 的时候,输出的是地址值;然后我们输出 arr[0],java就好根据索引去寻找数组中指定位置的值,然后输出;更改数组中变量的原理也是一样的。
注意:开辟的这块空间是连续的,所以我们可以根据索引去查找;而我们后面要学的链表,它的地址是不连续的。
至此,数组的基本知识,我们已经学习完毕了,当然这只是很简单很基础的。至于二维数组和其他的数组操作,我们后面慢慢讲