数组
一、概念
数组: 内存中一片连续的内存空间,可以存储多个类型相同的数据,方便统一进行处理.
元素: 就是数组中的每个数据
下标: 就是为每个元素分配的一个编号 0 ---- 数组的长度 - 1
数组的长度: 就是数组的容量,可以进行动态的获取 数组名.length
二、数组的定义
数组定义的步骤:
1. 数组的声明: 意义在于 确定了数组中存放的数据类型 以及 数组名 2. 为数组分配空间 / 为数组元素直接赋值 为数组分配空间: 先分配内存空间,在空间中存放默认值 ---> 类似于用书包 占座 为数组的元素直接赋值: 在定义数组的时候,将数组中要存放的数据直接进行存储 ----> 人 直接去占座
语法:
1. 声明 + 分配空间 (1) 先声明 再分配空间 语法: 数据类型[] 数组名; 数组名 = new 数据类型[数组的长度]; 案例: int[] a; a = new int[4]; (2) 声明的同时并分配空间 语法: 数据类型[] 数组名 = new 数据类型[数组的长度]; 案例: int[] a = new int[4]; 2. 声明 + 为元素赋值 (1) 先声明 再为元素赋值 语法: 数据类型[] 数组名; 数组名 = new 数据类型[]{元素1,元素,元素3.......}; 案例: int[] a; a = new int[]{1,2,3,4,5}; 注意: 在为元素进行赋值后,就不能再为其指定容量了 例如: int[] a; a = new int[5]{1,2,3,4,5}; ----> 错误 (2) 声明的同时并为元素赋值 语法: 数据类型[] 数组名 = new 数据类型[]{元素1,元素2,元素3.....}; 案例: int[] a = new int[]{1,2,3,4,5}; 简化的写法: 数据类型[] 数组名 = {元素1,元素2,元素3.......}; 注意事项: 当采用简化写法的时候,必须要求 数组的声明和数组元素的赋值 必须是同一条语句. 注意事项: 在定义数组的语法上 数据类型[] 数组名 是Java中标准的写法, 也可以使用c语言中 数据类型 数组名[]/ 数据类型 []数组名; 不建议
三、数组的使用
1、存储数据
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; //数据的存储 a[0] = 10; a[1] = 20; a[2] = 30; int[] b = {10,20,30}; }
2、访问数据
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; //数据的存储 a[0] = 10; a[1] = 20; a[2] = 30; //访问数据 System.out.println(a[0]); System.out.println(a[1]); System.out.println(a[2]); } }
3、修改数据
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; //数据的存储 a[0] = 10; a[1] = 20; a[2] = 30; //访问数据 System.out.println(a[0]); System.out.println(a[1]); System.out.println(a[2]); System.out.println("================================"); //修改数据 a[0] = 100; a[2] = 250; System.out.println(a[0]); System.out.println(a[1]); System.out.println(a[2]); } }
4、数组的遍历
遍历: 依次访问数组中的元素的过程叫做遍历 方式: 循环 + 数组名.length 进行遍历 。开发中一般采用的是 for 循环进行数组的遍历
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; //数据的存储 a[0] = 10; a[1] = 20; a[2] = 30; //访问数据 //System.out.println(a[0]); //System.out.println(a[1]); //System.out.println(a[2]); System.out.println("数组的长度为:"+a.length); // 通过循环的方式 挨个访问数组中的元素 ----> 数组的遍历 //for(int i = 0;i< a.length;i++){ // System.out.println(a[i]); //} int i = 0; while (i<a.length) { System.out.println(a[i]); i++; } } }
四、数组元素的默认值
类型 默认值
基本数据类型
整数类型 0
小数类型 0.0
字符类型 '\u0000'
布尔类型 false
引用数据类型 null
举例:
public class Demo{ public static void main(String[] args) { // a 基本数据类型变量 //int a = 20; //System.out.println(a);// 20 // b 数组类型变量 ---> 引用数类型 byte[] b = {1,2};// [I@15db9742 // [ ---> 代表 b 类型是一个数组 //I ----> Int 代表b 是一个int类型数组 // @ ----> 就是一个单纯 @ //15db9742 ----> 数组b在内存中的地址 ----> hash算法得到了一个对应的哈希值 int 十进制 ---> HextoString() ---> 转换为十六进制的形式 最终拼接成字符串 System.out.println(b); } }
五、数组的特点
1. 内存地址是连续的
2. 数组中存储的数据都是类型相同的
3. 数组一旦初始化完毕,其容量不可以变.
六、 数组中常见的异常
1、数组下标越界异常
导致的原因: 在访问数组的时候 下标不在 0 --- 数组名.length - 1 范围之内
举例:
public class Demo{ public static void main(String[] args) { int[] a = {1,2,3,4}; // 0 --- 3 System.out.println(a[0]); System.out.println(a[1]); System.out.println(a[2]); System.out.println(a[3]); System.out.println(a[4]); //编译报错: //ArrayIndexOutOfBoundsException } }
2、空指针异常
原因: 访问的数组在内存中找不到
举例:
public class Demo{ public static void main(String[] args) { int[] a = {1,2,3,4}; a = null; // null a不指向任何的内存地址 System.out.println(a[0]); //编译报错: //NullPointerException } }
七、数组的内存分析
1、JVM内存分析
2、数组的内存分析
(1)一个数组的内存分析
案例:
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; a[0] = 10; a[1] = 20; a[2] = 30; System.out.println(a[2]); } }
(2)两个数组的内存分析
举例:
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; a[0] = 10; a[1] = 20; a[2] = 30; System.out.println(a[2]); int[] b = {1,2,3,4}; System.out.println(b[3]); } }
(3)两个引用同时指向同一个数组
举例:
public class Demo{ public static void main(String[] args) { int[] a = new int[3]; a[0] = 10; a[1] = 20; a[2] = 30; System.out.println(a[2]); int[] b = {1,2,3,4}; System.out.println(b[3]); b = a;// 将a中的地址 赋值给 b System.out.println(b[1]);// } }
八、数组中常见操作
1、获取数组的最值
数组类型:int类型数组
思想 : 擂台思想,不断进行比较,选出最大或最小的那个值。
public class Demo{ public static void main(String[] args) { int[] a = {145,31,5,45,234,532,45,45}; //求最大值 // 设置一个擂台 默认放着 下标为0 的那个数据 int max = a[0]; for(int i = 1;i<a.length;i++){ //让其他的元素 依次和 max中的数据进行对比 如果大于 取而代之 if(a[i]>max){ max = a[i]; } } System.out.println("最大值是:"+max); } }
2、数组元素交换
要求:数组中的第一个元素 和 最后一个元素进行交换
方法:借助第三个变量
public class Demo{ public static void main(String[] args) { int[] a = {145,31,5,45,234,532,45,45}; int temp = a[0]; a[0] = a[a.length-1]; a[a.length-1] = temp; //遍历 for(int i = 0;i<a.length;i++){ System.out.println(a[i]); } } }
3、数组反转
什么是反转:数组中的第一个和最后一个调换顺序,第二个与倒数第二个调换顺序,其他依次。
举例:{1,2,3,4} -----> {4,3,2,1} 这就是数组反转,也可以称为逆序。
public class Demo{ public static void main(String[] args) { int[] a = {145,31,5,45,234,532,645,245}; for(int i = 0;i<a.length/2;i++){ // a[0] --- a[a.length -1 - 0] // a[1] ---- a[a.length - 1 -1] // a[i] --- a[a.length -1 -i] int temp = a[i]; a[i] = a[a.length-1-i]; a[a.length - 1-i] = temp; } //遍历 for(int i =0 ;i<a.length;i++){ System.out.println(a[i]); } } }
4、数组排序
排序: 排列顺序 从大到小 从小到大
排序算法有很多,比较基础的有冒泡排序的和选择排序。
(1)冒泡排序
冒泡排序规则: 相邻的两个元素进行比较,如果前者大于后者,那么两者交换位置(每次比较和移动的是相邻的两项)。
外层循环控制比较的轮数,也就是数组需要比较的数字数量。
内层循环控制每轮需要两两比较的次数(随着比较的进行,不断选出最大、次大值...,对于已经确定的值将不会在进行比较,因此每轮进行两两比较的数量会不断减一)
public class Demo1{ public static void main(String[] args) { int[] a = {3,4,1,2,5432,523,45,324,532,45,32,4532,45,3245,2,4532}; //从小到大排列 for(int i = 0; i< a.length;i++){//比的轮数 、 for(int k = 0; k< a.length - i;k++){ // k[i] ---k[i+1] // 如果前者大于后者 交换位置 if(a[k]>a[k+1]){ int temp = a[k]; a[k] = a[k+1]; a[k+1] = temp; } } } //排序成功 遍历 for(int i = 0; i<a.length;i++){ System.out.println(a[i]); } } }
(2)选择排序
选择排序规则: 两个元素进行比较,如果前者大于后者,那么两者交换位置,否则无变化(每一次交换的是当前项和第n项)。
import java.util.*; public class Demo1{ public static void main(String[] args) { int[] a = {3,4,1,2,5432,523,45,324,532,45,32,4532,45,3245,2,4532}; //从小到大排列 for(int i = 0; i < a.length ;i++) for(int j = i+1; k<= a.length; k++){ // k[i] ---k[j] // 如果a[i]大于a[j] 交换位置 if(a[i]>a[j]){ int temp = a[i]; a[i] = a[j]; a[j] = temp; } } } //快速排序: 可以使用 Arrays工具类中sort方法 //Arrays.sort(a); //排序成功 遍历 for(int i = 0; i<a.length;i++){ System.out.println(a[i]); } } }