p.s.这是萌新自己自学总结的笔记,如果想学习得更透彻的话还是请去看大佬的讲解
目录
数组概念
数组指的是一种容器,可以用来存储同种类型数据的多个值
但某种数据类型的数组也能存储数据类型的精度及容量比它低的数据
但还是建议最好容器的类型和存储的数据类型保持一致
数组定义
两种定义数组类型的格式
格式一:数据类型 [ ] 数组名
范例:int [ ] array
格式一:数据类型 数组名 [ ]
范例:int array [ ]
“[ ]” 即为数组的意思
数组的初始化
概念:就是在内存中,为数组容器开辟空间,并将数据存入容器中的过程
数组的初始化有两种形式:静态初始化和动态初始化
静态初始化
格式如下
数据类型 [] 数组名 = new 数据类型 [] {元素1,元素2,元素3······};
举例
int [] array = new int[]{11,22,33};
简化格式如下
数据类型 [] 数组名 = {元素1,元素2,元素3······};
举例
int [] array = {11,22,33};
当数组创建完毕后数组的长度就为数据总数且无法再改变了
动态初始化
动态初始化是由我们人工指定数组长度,而由系统为数组分配默认初始值
其中的默认初始值就是数据类型的初始值
格式如下
数据类型 [] 数组名 = new 数据类型 [数组长度];
举例
int [] arr = new int[3];
实际问题
public class shuzu4 {
public static void main(String[] args) {
//实际问题:定义一个数组,用来存储50个学生的姓名
//姓名未知,等学生报道后再进行添加
String [] arr = new String[50];
//添加学生信息
arr[0] = "张三";
arr[1] = "李四";
//获取学生信息
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);//打印出来的是默认初始化值
}
}
输出结果为
张三
李四
null
数组动态初始化和静态初始化的区别
动态初始化:手动指定数组长度,由系统给出默认初始化值
静态初始化:手动指定数组元素,系统会给定元素个数,计算出数组的长度
因此以后如果只明确元素个数,不明确具体数值,推荐使用动态初始化
(比如使用数组存储键盘输入的5个整数。这种就要使用数组动态初始化)
如果已经明确了要操作的具体数值,直接使用静态初始化即可
(比如要将全班学生的成绩存储到数组中。就可以使用静态初始化)
数组的地址值
数组的地址值就是数组在内存中的位置
举例
public class s {
public static void main(String[] args) {
double[] height = new double[]{1.70,1.72,1.73};
System.out.println(height);
}
}
输出结果为
[D@4eec7777
- 这一串字符即为数组的地址值
- “ [ ”表示当前是一个数组
- “D”则表示当前数组里面的元素都是double类型的
- “@”表示一个间隔符号,无固定意思
- “4eec7777”才是数组真正的地址值(十六进制)
- 但一般习惯性的会把这个整体叫做数组的地址值
数组元素访问
格式:数组名[索引];
索引
索引也叫做下标、角标。
索引其实就是数组容器中每个数据的编号
特点:从0开始逐个+1增长,连续不间断
通过索引可以把数组里面的元素获取出来,也可以通过索引将数据存储到数组当中
获取数组里的元素
格式:数组名[索引];
举例
int [] array = new int[]{12,13,15};
int x = array[0];
System.out.println(x);
输出结果为12
也可以写成这样
System.out.println(array[0]);
结果也一样
将数据/变量存储到数组中
格式
数据名 [索引] = 具体数据/变量;
注意:一旦存储后原来的数据就不存在了
数组的遍历
概念:将数组中的所有内容取出来
如果想将数组中的所有内容取出来可以写以下格式
int [] array = new int[]{12,13,15};
System.out.println(array[0]);
System.out.println(array[1]);
System.out.println(array[2]);
利用循环可以简化代码
从上面代码中我们可以得到几个线索
- 开始条件:0
- 结束条件:数组的长度-1(最大索引)
因此上述代码可简化为
int [] array = new int[]{12,13,15};
for (int i = 0;i < 3;i++){
System.out.println(array[i]);
}
但是当数组很长时就不容易得知结束循环的条件
而在JAVA里有一个关于数组的长度属性:length
调用方式:数组名.length
举例
int [] array = new int[]{12,13,15};
System.out.println(array.length);
输出结果:3
因此数据的遍历的形式为
int [] array = new int[]{12,13,15};
for (int i = 0;i < array.length;i++){
System.out.println(array[i]);
}
输出结果
12
13
15
简写方式
而IDEA提供了上述形式的便利书写方式(即缩写)
即输入数组名.fori
输出结果
for (int i = 0; i < array.length; i++) {
}
类似的还有
- 输入
sout
,即书写打印语句System.out.println();
- 输入
psvm
,即书写main方法
public static void main(String[] args) {
}
基础应用
public class s {
public static void main(String[] args) {
//定义一个数组,存储1,2,3,4,5,
//遍历数组,求数组里面所有的数据和
int [] arr = new int[]{1,2,3,4,5};
int x = 0;
for (int i = 0; i < arr.length; i++) {
x=x+i;
}
System.out.println(x);
}
}
输出结果为10
public class s {
public static void main(String[] args) {
//定义一个数组存储1-10,
//遍历数组并统计有多少个可以被三整除的数字
int []arr = new int[]{1,2,3,4,5,6,7,8,9,10};
int sum = 0;
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 3 == 0){
sum++;
}
}
System.out.println("能被3整除的数有"+sum+"个");
}
}
输出结果为能被3整除的数有3个
public class s {
public static void main(String[] args) {
//定义一个数组,存储1-10
//遍历数组,
//如果是奇数,则将数字扩大两倍
//如果是偶数,则将当前数字变成除以2
int[] arr = new int[]{1, 2, 3, 4, 5, 6, 7, 8, 9, 10};
for (int i = 0; i < arr.length; i++) {
if (arr[i] % 2 == 1) {
arr[i] = arr[i] * 2;
} else {
arr[i] = arr[i] / 2;
}
}
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
为什么不把打印语句放在一个for循环里呢?
那是因为要遵循一个原则,即为一个循环里最好只做一件事,防止书写代码时弄混淆
数组内存图
java内存分配给了5个大项
- 栈: 方法运行使用的内存,比如main方法运行,进入方法栈运行
- 堆: 存储对象和数组,new来创建的,都存储在堆内存
- 方法区: 存储可以运行的class文件
- 本地方法栈: JVM在使用操作系统功能时使用,与我们开发无关
- 寄存器: 给CPU使用,与我们开发无关
这一部分内容可以看黑马程序员进行学习(一维数组的内存图)
这一部分内容可以看黑马程序员进行学习(二维数组的内存图。25:08)
总结
- 只要是new出来的一定是在堆里面开辟了一个小空间,并且一定有地址值
- 如果new了多次,那么在堆里面有多个小空间,每个小空间中都有各自的数据
3。当两个数组指向同一个小空间时,其中一个数组对小空间中的值发生了改变,那么其他数组再次的时候都是修改之后的结果了
数组常见问题
索引越界问题
当访问了数组中不存在的索引时,就会引发索引越界异常(即会报错)
一般是由索引超出了数组长度导致的
举例
int [] arr = new int[]{1,2,3};
System.out.println(arr[10]);
运行后则会报错:
Exception in thread "main" java.lang.ArrayIndexOutOfBoundsException: Index 10 out of bounds for length 3 at s.main(s.java:6)
翻译为:程序中出现异常:在主线程中发生“java.lang.ArrayIndexOutOfBoundsException”错误(即发生了索引越界问题),索引为10,但数组长度为3。错误发生在文件“s.java”的第6行
二维数组
即数组中存数组
当我们需要把数据分类管理时,就需要用到二维数组
静态初始化
格式
数据类型[][] 数组名 = new 数据类型[][]{ {元素1,元素2},{元素1,元素2} };
或
数据类型 数组名[][] = new 数据类型[][]{ {元素1,元素2},{元素1,元素2} };
举例
int[][] arr = new int[][]{{12,11},{12,21}};
建议这样定义,增强了可读性
int[][] arr = new int[][]{
{12,11},
{12,21}
};
简化格式
数据类型[][] 数组名 = { {元素1,元素2},{元素1,元素2} };
举例
int[][] arr = {{12,11},{12,21}};
动态初始化
格式
数据类型 [][]数组名 = new 数据类型[m][n];
m表示这个二维数组能存放多少个一维数组
n表示每个一维数组可以存放多少个元素
举例
int [][]arr = new int[2][3];
这个二维数组可以存放2个一维数组,每个一维数组可以存放3个int类型元素
二维数组的两种初始化方法性质与一维数组一致
元素访问
举例
int[][] arr = new int[][]{{12,11},{13,21}};
System.out.println(arr[0]);
输出结果为
[I@4eec7777
此时得到的是二维数组中第一个一维数组,因此打印的结果便是第一个一维数组的地址值
因此想要获取元素,格式应该为
int[][] arr = new int[][]{{12,11},{13,21}};
System.out.println(arr[0][0]);
输出结果为12
。即获取了二维数组中第一个一维数组的0索引对应的元素
二维数组遍历
先得到一维数组,再遍历一维数组获取元素
举例
int[][] arr = new int[][]{{12,11},{13,21}};
//for外循环:遍历二维数组获取里面的每一个一维数组
//for内循环:遍历一维数组获取里面的每一个元素
for (int i = 0; i < arr.length; i++) {
//i表示二维数组中的每一个索引
for (int j = 0; j < arr[i].length; j++) {
//arr[i]表示二维数组中的每一个元素(一维数组)
//j表示一维数组中的每一个元素
System.out.println(arr[i][j]);
}
}
二维数组遍历还可以是下面这种形式
int[][] arr = new int[][]{{12,11},{13,21}};
//for外循环:遍历二维数组获取里面的每一个一维数组
//for内循环:遍历一维数组获取里面的每一个元素
for (int i = 0; i < arr.length; i++) {
//i表示二维数组中的每一个索引
for (int j = 0; j < arr[i].length; j++) {
//arr[i]表示二维数组中的每一个元素(一维数组)
//j表示一维数组中的每一个元素
System.out.print(arr[i][j]+ " ");
}
System.out.println();
}
输出结果为
12 11
13 21
这种形式不仅将每个数组中的元素打印在一行,还将不同的数组隔开,增强了可读性
二维数组特殊情况
特殊情况一:人为定义一维数组
举例
int [][]arr = new int[2][];
int[] arr1 = new int[]{1,3};
int[] arr2 = new int[]{11,22,33};
arr[0] = arr1;
arr[1] = arr2;
由于一维数组是由人为定义的,因此可以使二维数组中的每个一维数组的长度便可以不一样,提高了定义二维数组的灵活性
特殊情况二:人为修改一维数组
int [][]arr = new int[2][3];
int[] arr1 = new int[]{1,3};
int[] arr2 = new int[]{11,22,33};
arr[0] = arr1;
arr[1] = arr2;
通过将arr1和arr2赋值给了二维数组,使得二维数组里面本来的两个一维数组(元素全是初始值)被替换,从而实现了修改二维数组里面的一维数组的目的
二维数组基础应用
public class s {
public static void main(String[] args) {
//求每个季度的总营业额和全年的总营业额
//第一季度:10,20,30
//第二季度:15,25,35
//第三季度:11,21,31
//第四季度:12,22,32
int [][]arr = new int[][]{
{10,20,30},
{15,25,35},
{11,21,31},
{12,22,32}
};
int sum = 0;
for (int i = 0; i < arr.length; i++) {
int x = 0;
for (int j = 0; j < arr[i].length; j++) {
x = x +arr[i][j];
sum = sum +arr[i][j];
}
System.out.println("第"+(i+1)+"季度的营业额为"+x);
}
System.out.println("全年营业额为"+sum);
}
}