数组(Array)
概述 : 数组是一种容器,容器就是存储数据的,数组可以同时存储多个数据的容器.
比如 : 班级里面有100个同学,100个名字,定义变量的方式 ,需要定义出100个变量,存储名字
更好的解决办法 : 100个名字全部存储在一个容器中,方便管理这些个数据
凡是数据多了,存储在数组容器中.
Java数组 : 只能存储同一个数据类型的数据
数组的定义
-
定义数组的格式1:
数据类型,定义的数组容器存储的数据的类型 int 这个数组就只能存储整数
[] 就表示数组
数组的名字, 理解为就是一个变量的名字 (标识符,驼峰命名)
new 创建数组容器的关键字
数据类型,定义的数组容器存储的数据的类型 int 这个数组就只能存储整数
-
整数值, 表示的是数组的长度, 就是容量,也就数组能存储多少个数据
数据类型[] 数组的名字 = new 数据类型[整数值]; int[] arr = new int[3];
JVM内存划分
数组内存
- 栈内存和堆内存区别
- 栈内存,使用完毕就释放,效率高
- 堆内存,等待JVM垃圾回收,效率低
- 栈内存中的变量,必须赋值,否则不能使用
- 堆内存的数据,必须有默认值
- 栈内存,方法运行的时候计算
- 堆内存,负责存储对象和数组
数组的访问
操作数组中的数据了, 存储到数组中的任何数据,都称为数组的元素(Element)
数组元素的访问,依靠数组的索引 (index) (下标)
- 数组的索引
- 每个数组都有自己的索引
- 索引是从0开始的
- 索引是数组的特性,天生就有, 本质上就是数组中每个元素的编号
- 数组访问的语法:
- 数组名[索引]
public static void main(String[] args) {
//定义存储int类型的数组,数组的长度是3
int[] arr = new int[3];
//输出,数组0索引上的元素
System.out.println(arr[0]);
//输出,数组1索引上的元素
System.out.println(arr[1]);
//输出,数组2索引上的元素
System.out.println(arr[2]);
//数组0索引上的元素,赋值
arr[0] = 5;
System.out.println(arr[0]);
}
数组的长度
Java中的数组是定长的, 数组的长度,也就是存储元素的个数,一旦创建完毕,不可改变
定长也是数组的一个弊端
对于数组 : JVM赋予数组一个属性 (属性 : 属于这个事务的特性)
属性的名字 length, 表示数组的长度 (int类型)
使用方法 : 数组名.length
public static void main(String[] args) {
//定义数组,存储的类型是int类型,长度5
int[] arr = new int[5];
//使用数组的长度属性 length
//int l = arr.length;
System.out.println(arr.length);
}
数组长度length属性, 数组的最大索引,是长度-1 arr.length-1
数组的定义
-
定义格式2 : 定义数组的同时直接存储元素
- {}可以直接写入数组的元素值
数据类型[] 数组的名字 = new 数据类型[]{元素1,元素2,元素3};
public static void main(String[] args) { int[] arr = new int[] {1,2,3,4,5,6,7}; System.out.println(arr); //输出5, 在4索引的位置 System.out.println(arr[4]); //数组的长度length属性 System.out.println(arr.length); }
-
定义格式3:
数据类型[] 数组的名字 = {元素1,元素2,元素3};
public static void main(String[] args) { int[] arr = {1,2,3,4,5,6,7,8,9,0}; System.out.println(arr[7]); System.out.println(arr.length); }
数组操作的2个异常
数组的索引超过范围异常 (索引越界)
程序中访问了不存在的索引, 每个数组的索引范围从0开始,最大的索引=数组的长度-1
public static void main(String[] args) {
//定义存储int类型的数组
int[] arr = {1,2,3,4,5};
//数组中存储5个元素,长度是5个
System.out.println(arr.length);
//索引0-4
//访问不存在的索引
System.out.println(arr[5]);
}
数组的空指针异常
当数组的引用类型变量arr
不保存数组的地址了,再操作数组,就出现空指针异常
public static void main(String[] args) {
int[] arr = {1,2,3,4,5};
System.out.println(arr);
arr = null; //数组 = 空 , 不再保存数组在内存中的地址了
//不能操作数组的任何内容
System.out.println(arr.length);
}
数组的内存问题
两个数组在内存中的表现
每个数组,都会在内存中,开辟空间存储数据, 内存之间是相互独立的,没有关联
一个数组就会占用一个内存空间
public static void main(String[] args) {
//定义2个数组
int[] arr1 = new int[]{1,2,3,4,5};
int[] arr2 = new int[]{6,7,8,9,0};
//输出数组,看到不同的地址
System.out.println(arr1);
System.out.println(arr2);
System.out.println(arr1[0]);
System.out.println(arr2[0]);
}
多个变量指向同一个内存空间
public static void main(String[] args) {
//定义数组,存储一些元素
int[] arr1 = {1,2,3,4};
System.out.println(arr1);
//将数组arr1的内存地址,赋值到另一个变量
int[] arr2 = arr1;
System.out.println(arr2);
System.out.println(arr1[0]);
arr2[0] = 100;
System.out.println(arr1[0]);
}
数组的常见操作
数组的遍历 (迭代)
所谓数组的遍历,就是将数组中的每一个元素分别取出的过程.
数组的遍历,是数组其他操作的一个最基础的案例
循环遍历取出数组的元素,循环的次数由长度决定
int[] arr = {2,4,6,8,10};
//循环遍历数组,取出数组中的每个元素,依次取出
//数组的长度是5个,索引0-4 for(知道次数) while(不知道次数)
for(int i = 0 ; i < arr.length ; i++) {
//利用循环中的变量i, 作为索引使用,取出数组的元素
System.out.println(arr[i]);
}
}
数组最值获取
取出数组中的最大值,或者是最小值
实现核心思想 : 遍历中进行比较
* 获取数组的最大值
* 实现步骤 :
* 1.定义变量,保存数组0索引上的元素
* 2.遍历数组,取出数组的每个元素
* 3.数组的元素和变量,进行比较
* 如果数组的元素,大于变量
* 数组的元素,存储在变量中
* 4.数组全部遍历完成,变量保存的就是最大值
*/
public class ArrayDemo06 {
public static void main(String[] args) {
//创建数组
int[] arr = {1,5,10,2,6,9,0,7};
//定义变量,保存数组0索引上的元素
int max = arr[0];
//遍历数组,取出数组的每个元素
for(int i = 1 ; i < arr.length ; i++) {
//数组的元素,和变量max比较
if(arr[i] > max) {
//赋值变量
max = arr[i];
}
}
//数组全部遍历完成,变量保存的就是最大值
System.out.println("最大值是::"+max);
}
}
数组的倒序遍历
public static void main(String[] args) {
int[] arr = {1,3,5,7,9};
//从数组的最大索引开始遍历
for(int i = arr.length-1 ; i >= 0 ; i--) {
System.out.println(arr[i]);
}
}
数组拼接为字符串
任意数组 : int[] arr = {1,2,3,4,5,6,7}, 遍历数组,取出元素,元素拼接为一个字符串
输出的格式 [1,2,3,4,5,6,7]
/*
* 输出的格式 [1,2,3,4,5,6,7]
* 数组遍历,拼接成上面的格式
* 解决最后一个逗号问题 :
* 判断循环变量 i , 如果i的值,到达了数组的最大索引
* 字符串拼接] ,而不是逗号
*
*/
public class ArrayDemo08 {
public static void main(String[] args) {
//创建数组
int[] arr = {1,2,3,4,5,6,7};
//遍历,取出元素,字符串的拼接
String s = "[";
for(int i = 0 ; i < arr.length ;i++) {
//判断i是不是最大索引,如果是拼接]
if(i == arr.length - 1) {
s = s + arr[i]+"]";
}else {
s = s + arr[i]+",";
}
}
System.out.println(s);
}
}
数组元素的查找
已知数组 : 在数组中查找一个元素是否存在
元素存在于数组中 : 返回元素所在的索引
元素不存在数组中 : 返回负数
实现功能的核心思想 :
/*
* 数组元素基本查找
* 已知数组 : 在数组中查找一个元素是否存在
元素存在于数组中 : 返回元素所在的索引
元素不存在数组中 : 返回负数
实现功能的核心思想 : 遍历,进行比较
实现思想 :
1. 定义数组
2. 定义要查找的元素
3. 定义变量,保存查找后的结果 (数组的索引,或者是负数)
4: 遍历数组,取出每个元素,和要查找的元素对比
一旦找到,就不会在进行比较了
*/
public class ArrayDemo09 {
public static void main(String[] args) {
//1. 定义数组
int[] arr = {1,5,6,7,2,3,8};
//2. 定义要查找的元素
int key = 1;
//3. 定义变量,保存查找后的结果 (数组的索引,或者是负数)
int index = -1;
//4: 遍历数组,取出每个元素,和要查找的元素对比
for(int i = 0 ; i < arr.length ; i++) {
//查找的元素 和 数组的元素相等,找到了
if(key == arr[i]) {
//数组的索引,赋值到变量index
index = i;
//不需要再计算了吧,结束循环
break;
}
}
if(index >= 0) {
System.out.println("元素找到了,在"+index+"这个索引");
}else{
System.out.println("抱歉,元素未找到");
}
}
}
数组翻转
所谓数组翻转,就是数组中元素的位置发生了转变 不等于倒序遍历
原始数组 : {1,2,3,4,5}
翻转数据 : {5,4,3,2,1}
/*
* 数组的翻转
*
* 数组最远端的元素换位
*
* 实现思想 :
* 1. 定义2个变量
* 一个变量,保存数组的最小索引
* 一个变量,保存数组的最大索引
*
* 2: 当最小索引,超过最大的索引,程序结束
*
* 3: 利用循环实现
*
* 4: 第三方变量的位置交换
*/
public class ArrayDemo11 {
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,0};
//一个变量,保存数组的最小索引
//一个变量,保存数组的最大索引
int min = 0;
int max = arr.length - 1;
for(; min <= max ;) {
//第三方变量交换位置
int temp = arr[max]; //临时变量,保存数组的最大索引
//最小索引的元素,赋值到最大索引
arr[max] = arr[min];
//临时变量的值,赋值到小索引上
arr[min] = temp;
//位置交换完毕,修改索引
min++;
max--;
}
//数组遍历
for(int i = 0 ; i < arr.length ; i++) {
System.out.println(arr[i]);
}
}
}
以上程序小的优化
public static void main(String[] args) {
int[] arr = {1,2,3,4,5,0};
//一个变量,保存数组的最小索引
//一个变量,保存数组的最大索引
/* int min = 0;
int max = arr.length - 1;*/
for(int min = 0 , max = arr.length - 1; min <= max ;min++ ,max--) {
//第三方变量交换位置
int temp = arr[max]; //临时变量,保存数组的最大索引
//最小索引的元素,赋值到最大索引
arr[max] = arr[min];
//临时变量的值,赋值到小索引上
arr[min] = temp;
}
//数组遍历
for(int i = 0 ; i < arr.length ; i++) {
System.out.println(arr[i]);
}
}
二维数组
一维数组 : 一个数组,存储的是需要的数据 int[] arr = {123}
-
二维数组 : 一个数组,存储的元素,是另一个数组. 理解为数组中的数组
- 定义方式 :
数据类型[][] array = new 数据类型[3][2]; 格式解析 : 定义了一个二维数组 [3] : 二维数组的长度, 这个二维数组里面存储了3个一维数组 [2] : 每个一维数组的长度是2
- 二维数组中,存储的是一维数组的内存地址
public static void main(String[] args) { /* * 二维数组的长度是3,存储3个一维数组 * 每个一维数组,可以存储2个元素 */ int[][] array = new int[3][2]; System.out.println(array);// [[I@15db9742 //思考? System.out.println(array[0]); // [I@6d06d69c }
- 定义方式:
数据类型[][] array = new 数据类型[][]{}
创建数组直接赋值元素
public static void main(String[] args) {
int[][] array = new int[][] { {1,2},{3,4,5,6},{7,8,9} };
System.out.println(array);
//思考, 输出5
System.out.println(array[1][2]);
//数组的越界异常
System.out.println(array[2][2]);
}
- 定义方式:
数据类型[][] array = {};
public static void main(String[] args) {
int[][] array = { {1,2,3},{4,5},{6,7,8,9,0} };
System.out.println(array);
}
遍历
二维数组的遍历 : 和一维数组遍历几乎是一样的
利用嵌套循环,双for, 外循环,遍历二维数组,内循环,遍历一维数组
public static void main(String[] args) {
int[][] array = { {1,2,3},{4,5},{6,7,8,9,0} };
//外循环,遍历二维数组,取出里面的3个一维数组
for(int i = 0 ; i < array.length; i++) {
//System.out.println(array[i]);
//内循环,遍历每个一维数组
for(int j = 0; j