容器的概念
变量中只能存储一个数据,新的数据进来,老的数据将被替换,如果需要存储多个数据,需要使用容器。容器:是将多个数据存储到一起,每个数据称为该容器的元素。生活中的容器:水杯,衣柜,鞋柜,教室
数组概述
java中的数组就是一个容器,可以存储多个数据,但是数据的类型必须一致。特点如下:
- 可以存储多个数据
- 多个数据的类型必须保持一致
- 数组一旦创建,长度是永远不可以发生改变
数组的声明
- 格式一:数据类型[ ] 数组名字;
- 格式二:数据类型 数组名称[ ];
示例
package demo1;
public class Test {
public static void main(String[] args) {
//(1)定义一个存储int类型数组的变量arrayA
//int类型数组: 该容器中只能存储的是int类型的数字
int[] arrayA;
//System.out.println(arrayA);//错误的: arrayA只是一个用来存储数组的变量,但是目前没有向arrayA中存储数组
//(2)定义一个存储double类型数组的变量arrayB
//double类型数组: 该数组容器中只能存储double类型的数据
double arrayB[];
//(3)定义一个存储char类型数组的变量arrayC
//char类型数组: 该数组容器中只能存储char类型的数据
char[] arrayC;
}
}
注意事项:声明了数组,没有进行初始化是无法进行使用的
数组的初始化
方式一:
数组动态初始化,只给定数组的长度,由系统给出默认初始化值。
- 格式:数据类型[ ] 数组名称 = new 数据类型[长度];
数组定义格式详解:
- 左侧数据类型:?规定了数组中可以存储哪种类型的数据
- 左侧[ ]:表示数组的意思
- 数组名称:?就是给数组起个名字(相当于门牌号),方便找到并使用数组
- ?=:表示赋值,把具体的=右边new出来的数组容器,存储到=左边的数组变量中,但是存储的是数组在内存空间的地址值
- new:?创建数组容器的过程
- 右侧数据类型:和左侧保持一致
- 右侧[]中长度:是一个int数字,表示数组中可以存储数据的数量,也叫作数组长度
代码示例
public class Demo {
public static void main(String[] args) {
//(1)创建一个int类型的数组,可以存储3个int数据,给该数组起个名称叫做arrayA
int[] arrayA = new int[3];
//(2)创建一个double类型的数组,可以存储7个double数据,给该数组起个名称叫做arrayB
double[] arrayB = new double[7];
//(3)创建一个char类型的数组,可以存储5个char数据,给该数组起个名称叫做arrayC
char[] arrayC = new char[5];
}
}
方式二:数组静态初始化,在创建数组时,直接确定数组元素
- 标准格式:数据类型[ ] 数组名称 = new 数据类型[ ]{元素1,元素2,元素3,...元素n};
注意:
- 右侧[ ]中不能写长度,JVM会根据{ }中元素的数量计算/推导出数组的长度。只要右侧[ ]中写长度,就会报错
- { }中的每个元素之间有逗号(英文状态)隔开,最后一个元素后面没有逗号
代码示例
public class Demo {
public static void main(String[] args) {
//(1)创建一个int类型的数组,可以存储多个int数据100,200,300,给该数组起个名称叫做arrayA
int[] arrayA = new int[]{100,200,300};
//(2)创建一个double类型的数组,可以存储多个double数据1.1,2.2,3.3,4.4,5.5,6.6,7.7,给该数组起个名称叫做arrayB
double[] arrayB = new double[]{1.1,2.2,3.3,4.4,5.5,6.6,7.7};
//(3)创建一个char类型的数组,可以存储多个char数据'真','的','好','想','你',给该数组起个名称叫做arrayC
char[] arrayC = new char[]{'真','的','好','想','你'};
}
}
省略格式:数据类型[ ] 数组名称 = {元素1,元素2,元素3,...元素n};
//(1)创建一个int类型的数组,可以存储多个int数据100,200,300,给该数组起个名称叫做arrayA
int[] arrayA = {100,200,300};
//(2)创建一个double类型的数组,可以存储多个double数据1.1,2.2,3.3,4.4,5.5,6.6,7.7,给该数组起个名 称叫做arrayB
double[] arrayB = {1.1,2.2,3.3,4.4,5.5,6.6,7.7};
//(3)创建一个char类型的数组,可以存储多个char数据'真','的','好','想','你',给该数组起个名称叫做arrayC
char[] arrayC = {'真','的','好','想','你'};
注意:
- 省略格式右侧不用写长度,JVM根据{ }中数组元素的数量推导长度
- 虽然没有写new,底层仍然有new的过程
- 动态初始化和标准格式的静态初始化,可以分两步完成
- 简化格式静态初始化,不能分成两步完成
代码示例
public static void main(String[] args) {
//定义数组变量,未赋值
int[] arr;
arr = new int[3];//动态初始化指定数组长度
arr = new int[]{10, 20, 30};//标准格式静态初始化
System.out.println("-------------------");
int[] arr2;
//arr2 = {100,200,300};//错误: 简化格式静态初始化,不能分成两步完成
}
数组使用的前置知识
- 数组的长度属性: 每个数组都具有长度,而且是固定的,Java中赋予了数组的一个属性,可以获取到数组的长度,语 句为: 数组名.length ,属性length的执行结果是数组的长度,int类型结果。由次可以推断出,数组的最大索引值为 数组名.length-1 。
- 数组名称: 代表数组在内存空间的地址值,是一个十六进制的整数数字
- 索引: 每一个存储到数组的元素,都会自动的拥有一个编号,从0开始,这个自动编号称为数组索引(index),可以通过数组的索引访问到数组中的元素。该编号从0开始到最大值(数组长度 减 1),格式:数组名称[索引编号]
- 为数组中的元素赋值:数组名[索引] =?数值
- 获取出数组中的元素:变量?=?数组名[索引]
?数组元素有默认值
在java中,如果为数组分配了内存空间,那么系统会为数组元素指定默认值,该默认值与数组的数据类型有关。
数组操作的常见问题之越界异常
观察一下代码,运行后会出现什么结果
package demo1;
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
System.out.println(arr[3]);
}
}
创建数组,赋值
3
个元素,数组的索引就是
0
,
1
,
2
,没有
3
索引,因此我们不能访问数组中不存在的索引,程序运行后,将 会抛出 ArrayIndexOutOfBoundsException
数组越界异常。在开发中,数组的越界异常是
不能出现
的,一旦出现了,就必须要修改我们编写的代码
数组操作的常见问题之空指针异常
package demo1;
public class Test {
public static void main(String[] args) {
int[] arr = {1, 2, 3};
arr = null;
System.out.println(arr[0]);
}
}
arr = null
这行代码,意味着变量
arr
将不会在保存数组的内存地址,也就不允许再操作数组了,因此运行的时候会抛出 NullPointerException 空指针异常。在开发中,数组的越界异常是
不能出现
的,一旦出现了,就必须要修改我们编写的 代码。
数组原理内存图
内存概述
内存是计算机中的重要原件,临时存储区域,作用是运行程序。我们编写的程序是存放在硬盘中的,在硬盘中的程序是不会运行的,必须放进内存中才能运行,运行完毕后会清空内存。 Java虚拟机要运行程序,必须要对内存进行空间的分配和管理。
为了提高运算效率,就对空间进行了不同区域的划分,因为每一片区域都有特定的处理数据方式和内存管理方式。 、
JVM的内存划分:
一个数组内存图
查看下面代码
package demo1;
public class Test {
public static void main(String[] args) {
int[] arr = new int[3];
System.out.println(arr);//[I@5f150435
}
}
以上方法执行,输出的结果是
[I@5f150435
,这个是什么呢?是数组在内存中的地址。
new
出来的内容,都是在堆内存中存储的,而方法中的变量arr
保存的是数组的地址。
输出
arr[0]
,就会输出
arr
保存的内存地址中数组中
0
索引上的元素
结论:
- 数组名称保存数组在堆内存中的地址值
- 通过数组名称找到堆内存中的具体数组,然后通过索引编号找到对应的具体的某个元素
?两个数组内存图
查看下面代码
package demo1;
public class Test {
public static void main(String[] args) {
int[] arr = new int[3];
int[] arr2 = new int[2];
System.out.println(arr);
System.out.println(arr2);
}
}
图解
结论:
每个数组都有自己独立的内存空间,互不影响,互不干扰
两个变量指向一个数组
查看下面代码
package demo1;
public class Test {
public static void main(String[] args) {
// 定义数组,存储3个元素
int[] arr = new int[3]; //数组索引进行赋值
arr[0] = 5;
arr[1] = 6;
arr[2] = 7; //输出3个索引上的元素值
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
//定义数组变量arr2,将arr的地址赋值给arr2
int[] arr2 = arr;
arr2[1] = 9;
System.out.println(arr[1]);
}
}
图解
结论:
- 数组名称保存数组在堆内存空间的地址值
- 使用数组名进行赋值时,传递的是地址值
- 使用数组名作为方法参数和返回值,传递的都是地址值
数组练习
数组遍历:
就是将数组中的每个元素分别获取出来,就是遍历。遍历也是数组操作中的基石。
package demo1;
public class Test {
public static void main(String[] args) {
int[] arr = {11, 22, 33, 44, 55};
for (int i = 0; i < arr.length; i++) {
System.out.println(arr[i]);
}
}
}
综合练习?
import java.util.Scanner;
public class Test5Array {
/*
需求:在编程竞赛中,有6个评委为参赛的选手打分,分数为0-100的整数分。
选手的最后得分为:去掉一个最高分和一个最低分后 的4个评委平均值 (不考虑小数部分)。
思路:
1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
2.键盘录入评委分数
3.由于是6个评委打分,所以,接收评委分数的操作,用循环
4.求出数组最大值
5.求出数组最小值
6.求出数组总和
7.按照计算规则进行计算得到平均分
8.输出平均分
*/
public static void main(String[] args) {
// 1.定义一个数组,用动态初始化完成数组元素的初始化,长度为6
int[] arr = new int[6];
// 2.键盘录入评委分数
Scanner sc = new Scanner(System.in);
// 3.由于是6个评委打分,所以,接收评委分数的操作,用循环
for (int i = 0; i < arr.length; i++) {
System.out.println("请输入第" + (i+1) + "个评委的打分:");
int score = sc.nextInt();
if(score >= 0 && score <= 100){
// 合法的分值
arr[i] = score;
}else{
// 非法的分值
System.out.println("您的打分输入有误, 请检查是否是0-100之间的");
i--;
}
}
// 4.求出数组最大值
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if(max < arr[i]){
max = arr[i];
}
}
// 5.求出数组最小值
int min = arr[0];
for (int i = 1; i < arr.length; i++) {
if(min > arr[i]){
min = arr[i];
}
}
// 6.求出数组总和
int sum = 0;
for (int i = 0; i < arr.length; i++) {
sum += arr[i];
}
// 7.按照计算规则进行计算得到平均分
int avg = (sum - max - min ) / 4;
// 8.输出平均分
System.out.println(avg);
}
}
二维数组
二维数组也是一种容器,不同于一维数组,该容器存储的都是一维数组容器
动态初始化格式:数据类型[ ][ ] 变量名 = new 数据类型[m][n];
示例
public class Demo {
/*
动态初始化格式:
数据类型[][] 变量名 = new 数据类型[m][n];
m表示这个二维数组,可以存放多少个一维数组
n表示每一个一维数组,可以存放多少个元素
*/
public static void main(String[] args) {
// 数据类型[][] 变量名 = new 数据类型[m][n];
int[][] arr = new int[3][3];
/*
[[I@10f87f48
@ : 分隔符
10f87f48 : 十六进制内存地址
I : 数组中存储的数据类型
[[ : 几个中括号就代表的是几维数组
*/
System.out.println(arr);
/*
二维数组存储一维数组的时候, 存储的是一维数组的内存地址
*/
System.out.println(arr[0]);
System.out.println(arr[1]);
System.out.println(arr[2]);
System.out.println(arr[0][0]);
System.out.println(arr[1][1]);
System.out.println(arr[2][2]);
// 向二维数组中存储元素
arr[0][0] = 11;
arr[0][1] = 22;
arr[0][2] = 33;
arr[1][0] = 11;
arr[1][1] = 22;
arr[1][2] = 33;
arr[2][0] = 11;
arr[2][1] = 22;
arr[2][2] = 33;
// 从二维数组中取出元素并打印
System.out.println(arr[0][0]);
System.out.println(arr[0][1]);
System.out.println(arr[0][2]);
System.out.println(arr[1][0]);
System.out.println(arr[1][1]);
System.out.println(arr[1][2]);
System.out.println(arr[2][0]);
System.out.println(arr[2][1]);
System.out.println(arr[2][2]);
}
}
二维数组中存储的是一维数组,可以存入 提前创建好的一维数组
public class Demo {
/*
问题: 二维数组中存储的是一维数组, 那能不能存入 [提前创建好的一维数组] 呢 ?
答 : 可以的
*/
public static void main(String[] args) {
int[] arr1 = {11, 22, 33};
int[] arr2 = {44, 55, 66};
int[] arr3 = {77, 88, 99, 100};
int[][] arr = new int[3][3];
arr[2][3] = 100;
arr[0] = arr1;
arr[1] = arr2;
arr[2] = arr3;
System.out.println(arr[1][2]);
System.out.println(arr[2][3]);
}
}
二维数组静态初始化
- 完整格式 :?数据类型?变量名 = new 数据类型{ {元素1, 元素2...} , {元素1, 元素2...}
- 简化格式 :?数据类型?变量名 = { {元素1, 元素2...} , {元素1, 元素2...} ...};
示例代码
public class Demo {
/*
完整格式:数据类型[][] 变量名 = new 数据类型[][]{ {元素1, 元素2...} , {元素1, 元素2...} ...};
简化格式: 数据类型[][] 变量名 = { {元素1, 元素2...} , {元素1, 元素2...} ...};
*/
public static void main(String[] args) {
int[] arr1 = {11,22,33};
int[] arr2 = {44,55,66};
int[][] arr = {{11,22,33}, {44,55,66}};
System.out.println(arr[0][2]);
int[][] array = {arr1,arr2};
System.out.println(array[0][2]);
}
}
二维数组遍历
public class Demo {
/*
需求:
已知一个二维数组 arr = {{11, 22, 33}, {33, 44, 55}};
遍历该数组,取出所有元素并打印
步骤:
1. 遍历二维数组,取出里面每一个一维数组
2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素
*/
public static void main(String[] args) {
int[][] arr = {{11, 22, 33}, {33, 44, 55}};
// 1. 遍历二维数组,取出里面每一个一维数组
for (int i = 0; i < arr.length; i++) {
//System.out.println(arr[i]);
// 2. 在遍历的过程中,对每一个一维数组继续完成遍历,获取内部存储的每一个元素
//int[] temp = arr[i];
for (int j = 0; j < arr[i].length; j++) {
System.out.println(arr[i][j]);
}
}
}
}
二维数组求和
public class Demo {
/*
需求:
某公司季度和月份统计的数据如下:单位(万元)
第一季度:22,66,44
第二季度:77,33,88
第三季度:25,45,65
第四季度:11,66,99
步骤:
1. 定义求和变量,准备记录最终累加结果
2. 使用二维数组来存储数据,每个季度是一个一维数组,再将4个一维数组装起来
3. 遍历二维数组,获取所有元素,累加求和
4. 输出最终结果
*/
public static void main(String[] args) {
// 1. 定义求和变量,准备记录最终累加结果
int sum = 0;
// 2. 使用二维数组来存储数据,每个季度是一个一维数组,再将4个一维数组装起来
int[][] arr = {{22, 66, 44}, {77, 33, 88}, {25, 45, 65}, {11, 66, 99}};
// 3. 遍历二维数组,获取所有元素,累加求和
for (int i = 0; i < arr.length; i++) {
for (int j = 0; j < arr[i].length; j++) {
sum += arr[i][j];
}
}
// 4. 输出最终结果
System.out.println(sum);
}
}
|